All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFCv2 01/19] drm/i915: Provide a hook for selftests
@ 2016-12-20 13:07 Chris Wilson
  2016-12-20 13:07 ` [RFCv2 02/19] kselftests: Exercise hw-independent mock tests for i915.ko Chris Wilson
                   ` (19 more replies)
  0 siblings, 20 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:07 UTC (permalink / raw)
  To: intel-gfx

Some pieces of code are independent of hardware but are very tricky to
exercise through the normal userspace ABI or via debugfs hooks. Being
able to create mock unit tests and execute them through CI is vital.
Start by adding a central point where we can execute unit tests and
a parameter to enable them. This is disabled by default as the
expectation is that these tests will occasionally explode.

To facilitate integration with igt, any parameter beginning with
i915.igt__ is interpreted as a subtest executable independently via
igt/drv_selftest.

Two classes of selftests are recognised: mock unit tests and integration
tests. Mock unit tests are run as soon as the module is loaded, before
the device is probed. At that point there is no driver instantiated and
all hw interactions must be "mocked". This is very useful for writing
universal tests to exercise code not typically run on a broad range of
architectures. Alternatively, you can hook into the late selftests and
run when the device has been instantiated - hw interactions are real.

v2: Add a macro for compiling conditional code for mock objects inside
real objects.
v3: Differentiate between mock unit tests and late integration test.
v4: List the tests in natural order, use igt to sort after modparam.
v5: s/late/live/

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> #v1
---
 drivers/gpu/drm/i915/Kconfig.debug                 |  15 ++
 drivers/gpu/drm/i915/Makefile                      |   3 +
 drivers/gpu/drm/i915/i915_pci.c                    |  19 +-
 drivers/gpu/drm/i915/i915_selftest.h               |  91 +++++++++
 .../gpu/drm/i915/selftests/i915_live_selftests.h   |  11 +
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |  11 +
 drivers/gpu/drm/i915/selftests/i915_selftest.c     | 222 +++++++++++++++++++++
 7 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/i915_selftest.h
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_live_selftests.h
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_selftest.c

diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index 598551dbf62c..de051502e891 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -26,6 +26,7 @@ config DRM_I915_DEBUG
         select DRM_DEBUG_MM if DRM=y
 	select DRM_DEBUG_MM_SELFTEST
 	select DRM_I915_SW_FENCE_DEBUG_OBJECTS
+	select DRM_I915_SELFTEST
         default n
         help
           Choose this option to turn on extra driver debugging that may affect
@@ -59,3 +60,17 @@ config DRM_I915_SW_FENCE_DEBUG_OBJECTS
           Recommended for driver developers only.
 
           If in doubt, say "N".
+
+config DRM_I915_SELFTEST
+	bool "Enable selftests upon driver load"
+	depends on DRM_I915
+	default n
+	help
+	  Choose this option to allow the driver to perform selftests upon
+	  loading; also requires the i915.selftest=1 module parameter. To
+	  exit the module after running the selftests (i.e. to prevent normal
+	  module initialisation afterwards) use i915.selftest=-1.
+
+	  Recommended for driver developers only.
+
+	  If in doubt, say "N".
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5196509e71cf..461aeb44a9ad 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -3,6 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 subdir-ccflags-$(CONFIG_DRM_I915_WERROR) := -Werror
+subdir-ccflags-$(CONFIG_DRM_I915_SELFTEST) := -I$(src) -I$(src)/selftests
 subdir-ccflags-y += \
 	$(call as-instr,movntdqa (%eax)$(comma)%xmm0,-DCONFIG_AS_MOVNTDQA)
 
@@ -114,6 +115,8 @@ i915-y += dvo_ch7017.o \
 
 # Post-mortem debug and GPU hang state capture
 i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
+i915-$(CONFIG_DRM_I915_SELFTEST) += \
+	selftests/i915_selftest.o
 
 # virtual gpu code
 i915-y += i915_vgpu.o
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 9885458b0fb8..3d416d142573 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -27,6 +27,7 @@
 #include <linux/vga_switcheroo.h>
 
 #include "i915_drv.h"
+#include "i915_selftest.h"
 
 #define GEN_DEFAULT_PIPEOFFSETS \
 	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
@@ -477,6 +478,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct intel_device_info *intel_info =
 		(struct intel_device_info *) ent->driver_data;
+	int err;
 
 	if (IS_ALPHA_SUPPORT(intel_info) && !i915.alpha_support) {
 		DRM_INFO("The driver support for your hardware in this kernel version is alpha quality\n"
@@ -500,7 +502,17 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (vga_switcheroo_client_probe_defer(pdev))
 		return -EPROBE_DEFER;
 
-	return i915_driver_load(pdev, ent);
+	err = i915_driver_load(pdev, ent);
+	if (err)
+		return err;
+
+	err = i915_live_selftests(pdev);
+	if (err) {
+		i915_driver_unload(pci_get_drvdata(pdev));
+		return err > 0 ? -ENOTTY : err;
+	}
+
+	return 0;
 }
 
 static void i915_pci_remove(struct pci_dev *pdev)
@@ -522,6 +534,11 @@ static struct pci_driver i915_pci_driver = {
 static int __init i915_init(void)
 {
 	bool use_kms = true;
+	int err;
+
+	err = i915_mock_selftests();
+	if (err)
+		return err > 0 ? 0 : err;
 
 	/*
 	 * Enable KMS by default, unless explicitly overriden by
diff --git a/drivers/gpu/drm/i915/i915_selftest.h b/drivers/gpu/drm/i915/i915_selftest.h
new file mode 100644
index 000000000000..6b3d1192e092
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_selftest.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __I915_SELFTEST_H__
+#define __I915_SELFTEST_H__
+
+struct pci_dev;
+struct drm_i915_private;
+
+struct i915_selftest {
+	unsigned long timeout_jiffies;
+	unsigned int timeout_ms;
+	unsigned int random_seed;
+	int mock;
+	int live;
+};
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+extern struct i915_selftest i915_selftest;
+
+int i915_mock_selftests(void);
+int i915_live_selftests(struct pci_dev *pdev);
+
+/* We extract the function declarations from i915_mock_selftests.h and
+ * i915_live_selftests.h Add your unit test declarations there!
+ *
+ * Mock unit tests are run very early upon module load, before the driver
+ * is probed. All hardware interactions, as well as other subsystems, must
+ * be "mocked".
+ *
+ * Late unit tests are run after the driver is loaded - all hardware
+ * interactions are real.
+ */
+#define selftest(name, func) int func(void);
+#include "i915_mock_selftests.h"
+#undef selftest
+#define selftest(name, func) int func(struct drm_i915_private *i915);
+#include "i915_live_selftests.h"
+#undef selftest
+
+struct i915_subtest {
+	int (*func)(void *data);
+	const char *name;
+};
+
+int __i915_subtests(const char *caller,
+		    const struct i915_subtest *st,
+		    int count,
+		    void *data);
+#define i915_subtests(T, data) \
+	__i915_subtests(__func__, T, ARRAY_SIZE(T), data)
+
+#define SUBTEST(x) { x, #x }
+
+#define I915_SELFTEST_DECLARE(x) x
+#define I915_SELFTEST_ONLY(x) unlikely(x)
+
+#else /* !IS_ENABLED(CONFIG_DRM_I915_SELFTEST) */
+
+static inline int i915_mock_selftests(void) { return 0; }
+static inline int i915_live_selftests(struct pci_dev *pdev) { return 0; }
+
+#define I915_SELFTEST_DECLARE(x)
+#define I915_SELFTEST_ONLY(x) 0
+
+#endif
+
+#define I915_SELFTEST_TIMEOUT(name__) \
+	unsigned long name__ = jiffies + i915_selftest.timeout_jiffies
+
+#endif /* !__I915_SELFTEST_H__ */
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
new file mode 100644
index 000000000000..f3e17cb10e05
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -0,0 +1,11 @@
+/* List each unit test as selftest(name, function)
+ *
+ * The name is used as both an enum and expanded as subtest__name to create
+ * a module parameter. It must be unique and legal for a C identifier.
+ *
+ * The function should be of type int function(void). It may be conditionally
+ * compiled using #if IS_ENABLED(DRM_I915_SELFTEST).
+ *
+ * Tests are executed in order by igt/drv_selftest
+ */
+selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
new file mode 100644
index 000000000000..69e97a2ba4a6
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -0,0 +1,11 @@
+/* List each unit test as selftest(name, function)
+ *
+ * The name is used as both an enum and expanded as subtest__name to create
+ * a module parameter. It must be unique and legal for a C identifier.
+ *
+ * The function should be of type int function(void). It may be conditionally
+ * compiled using #if IS_ENABLED(DRM_I915_SELFTEST).
+ *
+ * Tests are executed in order by igt/drv_selftest
+ */
+selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */
diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c
new file mode 100644
index 000000000000..4876f974edb8
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/random.h>
+
+#include "i915_drv.h"
+#include "i915_selftest.h"
+
+struct i915_selftest i915_selftest __read_mostly = {
+	.timeout_ms = 1000,
+};
+
+int i915_mock_sanitycheck(void)
+{
+	pr_info("i915: %s() - ok!\n", __func__);
+	return 0;
+}
+
+int i915_live_sanitycheck(struct drm_i915_private *i915)
+{
+	pr_info("%s: %s() - ok!\n", i915->drm.driver->name, __func__);
+	return 0;
+}
+
+enum {
+#define selftest(name, func) mock_##name,
+#include "i915_mock_selftests.h"
+#undef selftest
+};
+enum {
+#define selftest(name, func) live_##name,
+#include "i915_live_selftests.h"
+#undef selftest
+};
+
+struct selftest {
+	bool enabled;
+	const char *name;
+	union {
+		int (*mock)(void);
+		int (*live)(struct drm_i915_private *);
+	};
+};
+
+#define selftest(n, f) [mock_##n] = { .name = #n, .mock = f },
+static struct selftest mock_selftests[] = {
+#include "i915_mock_selftests.h"
+};
+#undef selftest
+
+#define selftest(n, f) [live_##n] = { .name = #n, .live = f },
+static struct selftest live_selftests[] = {
+#include "i915_live_selftests.h"
+};
+#undef selftest
+
+/* Embed the line number into the parameter name so that we can order tests */
+#define selftest(n, func) selftest_0(n, func, param(n))
+#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), mock_##n))
+#define selftest_0(n, func, id) \
+module_param_named(id, mock_selftests[mock_##n].enabled, bool, 0400);
+#include "i915_mock_selftests.h"
+#undef selftest_0
+#undef param
+
+#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), live_##n))
+#define selftest_0(n, func, id) \
+module_param_named(id, live_selftests[live_##n].enabled, bool, 0400);
+#include "i915_live_selftests.h"
+#undef selftest_0
+#undef param
+#undef selftest
+
+static void set_default_test_all(struct selftest *st, unsigned long count)
+{
+	unsigned long i;
+
+	for (i = 0; i < count; i++)
+		if (st[i].enabled)
+			return;
+
+	for (i = 0; i < count; i++)
+		st[i].enabled = true;
+}
+
+static int run_selftests(const char *name,
+			 struct selftest *st,
+			 unsigned long count,
+			 void *data)
+{
+	int err = 0;
+
+	while (!i915_selftest.random_seed)
+		i915_selftest.random_seed = get_random_int();
+
+	i915_selftest.timeout_jiffies =
+		i915_selftest.timeout_ms ?
+		msecs_to_jiffies_timeout(i915_selftest.timeout_ms) :
+		MAX_SCHEDULE_TIMEOUT;
+
+	set_default_test_all(st, count);
+
+	pr_info("i915: Performing %s selftests with st_random_seed=%x and st_timeout=%u\n",
+		name, i915_selftest.random_seed, i915_selftest.timeout_ms);
+
+	/* Tests are listed in order in i915_*_selftests.h */
+	for (; count--; st++) {
+		if (!st->enabled)
+			continue;
+
+		cond_resched();
+		if (signal_pending(current))
+			return -EINTR;
+
+		pr_debug("i915: Running %s\n", st->name);
+		if (data)
+			err = st->live(data);
+		else
+			err = st->mock();
+		if (err)
+			break;
+	}
+
+	if (WARN(err > 0 || err == -ENOTTY,
+		 "%s returned %d, conflicting with selftest's magic values!\n",
+		 st->name, err))
+		err = -1;
+
+	rcu_barrier();
+	return err;
+}
+
+#define run_selftests(x, data) \
+	(run_selftests)(#x, x##_selftests, ARRAY_SIZE(x##_selftests), data)
+
+int i915_mock_selftests(void)
+{
+	int err;
+
+	if (!i915_selftest.mock)
+		return 0;
+
+	err = run_selftests(mock, NULL);
+	if (err)
+		return err;
+
+	if (i915_selftest.mock < 0)
+		return 1;
+
+	return 0;
+}
+
+int i915_live_selftests(struct pci_dev *pdev)
+{
+	int err;
+
+	if (!i915_selftest.live)
+		return 0;
+
+	err = run_selftests(live, to_i915(pci_get_drvdata(pdev)));
+	if (err)
+		return err;
+
+	if (i915_selftest.live < 0)
+		return 1;
+
+	return 0;
+}
+
+int __i915_subtests(const char *caller,
+		    const struct i915_subtest *st,
+		    int count,
+		    void *data)
+{
+	int err;
+
+	for (; count--; st++) {
+		cond_resched();
+		if (signal_pending(current))
+			return -EINTR;
+
+		pr_debug("i915: Running %s/%s\n", caller, st->name);
+		err = st->func(data);
+		if (err) {
+			if (err != -EINTR)
+				pr_err("i915/%s: %s failed with error %d\n",
+				       caller, st->name, err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+module_param_named(st_random_seed, i915_selftest.random_seed, uint, 0400);
+module_param_named(st_timeout, i915_selftest.timeout_ms, uint, 0400);
+
+module_param_named_unsafe(mock_selftests, i915_selftest.mock, int, 0400);
+MODULE_PARM_DESC(mock_selftests, "Run selftests before loading, using mock hardware (0:disabled [default], 1:run tests then load driver, -1:run tests then exit module)");
+
+module_param_named_unsafe(live_selftests, i915_selftest.live, int, 0400);
+MODULE_PARM_DESC(live_selftests, "Run selftests after driver initialisation on the live system (0:disabled [default], 1:run tests then continue, -1:run tests then exit module)");
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 02/19] kselftests: Exercise hw-independent mock tests for i915.ko
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
@ 2016-12-20 13:07 ` Chris Wilson
  2016-12-20 13:07 ` [RFCv2 03/19] drm/i915: Add some selftests for sg_table manipulation Chris Wilson
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: Shuah Khan, linux-kselftest

Although being a GPU driver most functionality of i915.ko depends upon
real hardware, many of its internal interfaces can be "mocked" and so
tested independently of any hardware. Expanding the test coverage is not
only useful for i915.ko, but should provide some integration tests for
core infrastructure as well.

Loading i915.ko with mock_selftests=-1 will cause it to execute its mock
tests then exit before attempting to probe hardware. If the driver is
already loaded and bound to hardware, it requires a few more steps to
unbind, and so the simple preliminary modprobe -r will fail, causing the
test to be skipped.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
---
 tools/testing/selftests/drivers/gpu/i915.sh | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100755 tools/testing/selftests/drivers/gpu/i915.sh

diff --git a/tools/testing/selftests/drivers/gpu/i915.sh b/tools/testing/selftests/drivers/gpu/i915.sh
new file mode 100755
index 000000000000..c06d6e8a8dcc
--- /dev/null
+++ b/tools/testing/selftests/drivers/gpu/i915.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Runs hardware independent tests for i915 (drivers/gpu/drm/i915)
+
+if ! /sbin/modprobe -q -r i915; then
+	echo "drivers/gpu/i915: [SKIP]"
+	exit 77
+fi
+
+if /sbin/modprobe -q i915 mock_selftests=-1; then
+	/sbin/modprobe -q -r i915
+	echo "drivers/gpu/i915: ok"
+else
+	echo "drivers/gpu/i915: [FAIL]"
+	exit 1
+fi
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 03/19] drm/i915: Add some selftests for sg_table manipulation
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
  2016-12-20 13:07 ` [RFCv2 02/19] kselftests: Exercise hw-independent mock tests for i915.ko Chris Wilson
@ 2016-12-20 13:07 ` Chris Wilson
  2016-12-20 13:07 ` [RFCv2 04/19] drm/i915: Add unit tests for the breadcrumb rbtree, insert/remove Chris Wilson
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:07 UTC (permalink / raw)
  To: intel-gfx

Start exercising the scattergather lists, especially looking at
iteration after coalescing.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c                    |  11 +-
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |   1 +
 drivers/gpu/drm/i915/selftests/scatterlist.c       | 255 +++++++++++++++++++++
 3 files changed, 264 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/selftests/scatterlist.c

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 891e479dbf5d..4547d4cd2064 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2315,17 +2315,17 @@ static unsigned int swiotlb_max_size(void)
 #endif
 }
 
-static void i915_sg_trim(struct sg_table *orig_st)
+static bool i915_sg_trim(struct sg_table *orig_st)
 {
 	struct sg_table new_st;
 	struct scatterlist *sg, *new_sg;
 	unsigned int i;
 
 	if (orig_st->nents == orig_st->orig_nents)
-		return;
+		return false;
 
 	if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL | __GFP_NOWARN))
-		return;
+		return false;
 
 	new_sg = new_st.sgl;
 	for_each_sg(orig_st->sgl, sg, orig_st->nents, i) {
@@ -2338,6 +2338,7 @@ static void i915_sg_trim(struct sg_table *orig_st)
 	sg_free_table(orig_st);
 
 	*orig_st = new_st;
+	return true;
 }
 
 static struct sg_table *
@@ -4972,3 +4973,7 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
 	sg = i915_gem_object_get_sg(obj, n, &offset);
 	return sg_dma_address(sg) + (offset << PAGE_SHIFT);
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/scatterlist.c"
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index 69e97a2ba4a6..8639bb8fd50d 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -9,3 +9,4 @@
  * Tests are executed in order by igt/drv_selftest
  */
 selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */
+selftest(scatterlist, mock_scatterlist_selftests)
diff --git a/drivers/gpu/drm/i915/selftests/scatterlist.c b/drivers/gpu/drm/i915/selftests/scatterlist.c
new file mode 100644
index 000000000000..9bc3bc6dbc41
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/scatterlist.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/prime_numbers.h>
+
+#include "i915_selftest.h"
+
+#define PFN_BIAS (1 << 10)
+
+struct pfn_table {
+	struct sg_table st;
+	unsigned long start, end;
+};
+
+static noinline int expect_pfn_sg(struct pfn_table *pt, const char *who)
+{
+	struct scatterlist *sg;
+	unsigned long pfn, n;
+
+	pfn = pt->start;
+	for_each_sg(pt->st.sgl, sg, pt->st.nents, n) {
+		struct page *page = sg_page(sg);
+
+		if (page_to_pfn(page) != pfn) {
+			pr_err("%s left pages out of order, expected pfn %lu, found pfn %lu (using for_each_sg)\n",
+			       who, pfn, page_to_pfn(page));
+			return -EINVAL;
+		}
+
+		if (sg->length != (n + 1) * PAGE_SIZE) {
+			pr_err("%s: %s copied wrong sg length, expected size %lu, found %u (using for_each_sg)\n",
+			       __func__, who, (n + 1) * PAGE_SIZE, sg->length);
+			return -EINVAL;
+		}
+
+		cond_resched();
+		if (signal_pending(current))
+			return -EINTR;
+
+		pfn += n + 1;
+	}
+	if (pfn != pt->end) {
+		pr_err("%s: %s finished on wrong pfn, expected %lu, found %lu\n",
+		       __func__, who, pt->end, pfn);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static noinline int expect_pfn_sg_page_iter(struct pfn_table *pt, const char *who)
+{
+	struct sg_page_iter sgiter;
+	unsigned long pfn;
+
+	pfn = pt->start;
+	for_each_sg_page(pt->st.sgl, &sgiter, pt->st.nents, 0) {
+		struct page *page = sg_page_iter_page(&sgiter);
+
+		if (page != pfn_to_page(pfn)) {
+			pr_err("%s: %s left pages out of order, expected pfn %lu, found pfn %lu (using for_each_sg_page)\n",
+			       __func__, who, pfn, page_to_pfn(page));
+			return -EINVAL;
+		}
+
+		cond_resched();
+		if (signal_pending(current))
+			return -EINTR;
+
+		pfn++;
+	}
+	if (pfn != pt->end) {
+		pr_err("%s: %s finished on wrong pfn, expected %lu, found %lu\n",
+		       __func__, who, pt->end, pfn);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static noinline int expect_pfn_sgtiter(struct pfn_table *pt, const char *who)
+{
+	struct sgt_iter sgt;
+	struct page *page;
+	unsigned long pfn;
+
+	pfn = pt->start;
+	for_each_sgt_page(page, sgt, &pt->st) {
+		if (page != pfn_to_page(pfn)) {
+			pr_err("%s: %s left pages out of order, expected pfn %lu, found pfn %lu (using for_each_sgt_page)\n",
+			       __func__, who, pfn, page_to_pfn(page));
+			return -EINVAL;
+		}
+
+		cond_resched();
+		if (signal_pending(current))
+			return -EINTR;
+
+		pfn++;
+	}
+	if (pfn != pt->end) {
+		pr_err("%s: %s finished on wrong pfn, expected %lu, found %lu\n",
+		       __func__, who, pt->end, pfn);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int expect_pfn_sgtable(struct pfn_table *pt, const char *who)
+{
+	int err;
+
+	err = expect_pfn_sg(pt, who);
+	if (err)
+		return err;
+
+	err = expect_pfn_sg_page_iter(pt, who);
+	if (err)
+		return err;
+
+	err = expect_pfn_sgtiter(pt, who);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static bool alloc_table(struct pfn_table *pt,
+			unsigned long count,
+			unsigned long max)
+{
+	struct scatterlist *sg;
+	unsigned long n, pfn;
+
+	if (sg_alloc_table(&pt->st, max,
+			   GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN))
+		return false;
+
+	pt->start = PFN_BIAS;
+	pfn = pt->start;
+	sg = pt->st.sgl;
+	for (n = 0; n < count; n++) {
+		if (n)
+			sg = sg_next(sg);
+		sg_set_page(sg, pfn_to_page(pfn), (n + 1)*PAGE_SIZE, 0);
+		pfn += n + 1;
+	}
+	sg_mark_end(sg);
+	pt->st.nents = n;
+	pt->end = pfn;
+
+	return true;
+}
+
+static int igt_sg_alloc(void *ignored)
+{
+	I915_SELFTEST_TIMEOUT(end_time);
+	const unsigned long max_order = 20; /* approximating a 4GiB object */
+	unsigned long prime;
+
+	for_each_prime_number(prime, max_order) {
+		unsigned long size = BIT(prime);
+		int offset;
+
+		for (offset = -1; offset <= 1; offset++) {
+			struct pfn_table pt;
+			int err;
+
+			if (!alloc_table(&pt, size + offset, size + offset))
+				return 0; /* out of memory, give up */
+
+			err = expect_pfn_sgtable(&pt, "sg_alloc_table");
+			sg_free_table(&pt.st);
+			if (err)
+				return err;
+
+			if (time_after(jiffies, end_time)) {
+				pr_warn("%s timed out: last table size %lu\n",
+					__func__, size + offset);
+				return 0;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int igt_sg_trim(void *ignored)
+{
+	I915_SELFTEST_TIMEOUT(end_time);
+	const unsigned long max = PAGE_SIZE; /* not prime! */
+	struct pfn_table pt;
+	unsigned long prime;
+
+	for_each_prime_number(prime, max) {
+		int err;
+
+		if (!alloc_table(&pt, prime, max))
+			return 0; /* out of memory, give up */
+
+		err = 0;
+		if (i915_sg_trim(&pt.st)) {
+			if (pt.st.orig_nents != prime ||
+			    pt.st.nents != prime) {
+				pr_err("i915_sg_trim failed (nents %u, orig_nents %u), expected %lu\n",
+				       pt.st.nents, pt.st.orig_nents, prime);
+				err = -EINVAL;
+			} else {
+				err = expect_pfn_sgtable(&pt, "i915_sg_trim");
+			}
+		}
+		sg_free_table(&pt.st);
+		if (err)
+			return err;
+
+		if (time_after(jiffies, end_time)) {
+			pr_warn("%s timed out: last trim size %lu/%lu\n",
+				__func__, prime, max);
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+int mock_scatterlist_selftests(void)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_sg_alloc),
+		SUBTEST(igt_sg_trim),
+	};
+
+	return i915_subtests(tests, NULL);
+}
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 04/19] drm/i915: Add unit tests for the breadcrumb rbtree, insert/remove
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
  2016-12-20 13:07 ` [RFCv2 02/19] kselftests: Exercise hw-independent mock tests for i915.ko Chris Wilson
  2016-12-20 13:07 ` [RFCv2 03/19] drm/i915: Add some selftests for sg_table manipulation Chris Wilson
@ 2016-12-20 13:07 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 05/19] drm/i915: Add unit tests for the breadcrumb rbtree, completion Chris Wilson
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:07 UTC (permalink / raw)
  To: intel-gfx

First retroactive test, make sure that the waiters are in global seqno
order after random inserts and removals.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/Makefile                      |   1 +
 drivers/gpu/drm/i915/intel_breadcrumbs.c           |  21 +++
 drivers/gpu/drm/i915/intel_engine_cs.c             |   4 +
 drivers/gpu/drm/i915/intel_ringbuffer.h            |   2 +
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |   1 +
 drivers/gpu/drm/i915/selftests/i915_random.c       |  63 ++++++++
 drivers/gpu/drm/i915/selftests/i915_random.h       |  47 ++++++
 drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 173 +++++++++++++++++++++
 drivers/gpu/drm/i915/selftests/mock_engine.c       |  55 +++++++
 drivers/gpu/drm/i915/selftests/mock_engine.h       |  32 ++++
 10 files changed, 399 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_random.c
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_random.h
 create mode 100644 drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_engine.c
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_engine.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 461aeb44a9ad..2844b2d643e4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -116,6 +116,7 @@ i915-y += dvo_ch7017.o \
 # Post-mortem debug and GPU hang state capture
 i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
 i915-$(CONFIG_DRM_I915_SELFTEST) += \
+	selftests/i915_random.o \
 	selftests/i915_selftest.o
 
 # virtual gpu code
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index fcfa423d08bd..5682c8aa8064 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -109,6 +109,18 @@ static void __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
 	if (b->rpm_wakelock)
 		return;
 
+	if (I915_SELFTEST_ONLY(b->mock)) {
+		/* For our mock objects we want to avoid interaction
+		 * with the real hardware (which is not set up). So
+		 * we simply pretend we have enabled the powerwell
+		 * and the irq, and leave it up to the mock
+		 * implementation to call intel_engine_wakeup()
+		 * itself when it wants to simulate a user interrupt,
+		 */
+		b->rpm_wakelock = true;
+		return;
+	}
+
 	/* Since we are waiting on a request, the GPU should be busy
 	 * and should have its own rpm reference. For completeness,
 	 * record an rpm reference for ourselves to cover the
@@ -143,6 +155,11 @@ static void __intel_breadcrumbs_disable_irq(struct intel_breadcrumbs *b)
 	if (!b->rpm_wakelock)
 		return;
 
+	if (I915_SELFTEST_ONLY(b->mock)) {
+		b->rpm_wakelock = false;
+		return;
+	}
+
 	if (b->irq_enabled) {
 		irq_disable(engine);
 		b->irq_enabled = false;
@@ -661,3 +678,7 @@ unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915)
 
 	return mask;
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/intel_breadcrumbs.c"
+#endif
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 97bbbc3d6aa8..c6332096d870 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -482,3 +482,7 @@ void intel_engine_get_instdone(struct intel_engine_cs *engine,
 		break;
 	}
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/mock_engine.c"
+#endif
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 0969de7d5ab7..5b10e2d1c9a8 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -5,6 +5,7 @@
 #include "i915_gem_batch_pool.h"
 #include "i915_gem_request.h"
 #include "i915_gem_timeline.h"
+#include "i915_selftest.h"
 
 #define I915_CMD_HASH_ORDER 9
 
@@ -244,6 +245,7 @@ struct intel_engine_cs {
 
 		bool irq_enabled : 1;
 		bool rpm_wakelock : 1;
+		I915_SELFTEST_DECLARE(bool mock : 1);
 	} breadcrumbs;
 
 	/*
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index 8639bb8fd50d..fdee6c88e415 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -10,3 +10,4 @@
  */
 selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */
 selftest(scatterlist, mock_scatterlist_selftests)
+selftest(breadcrumbs, intel_breadcrumbs_selftest)
diff --git a/drivers/gpu/drm/i915/selftests/i915_random.c b/drivers/gpu/drm/i915/selftests/i915_random.c
new file mode 100644
index 000000000000..606a237fed17
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_random.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "i915_random.h"
+
+static inline u32 i915_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
+{
+	return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
+}
+
+void i915_random_reorder(unsigned int *order, unsigned int count,
+			 struct rnd_state *state)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < count; ++i) {
+		BUILD_BUG_ON(sizeof(unsigned int) > sizeof(u32));
+		j = i915_prandom_u32_max_state(count, state);
+		swap(order[i], order[j]);
+	}
+}
+
+unsigned int *i915_random_order(unsigned int count, struct rnd_state *state)
+{
+	unsigned int *order, i;
+
+	order = kmalloc_array(count, sizeof(*order), GFP_TEMPORARY);
+	if (!order)
+		return order;
+
+	for (i = 0; i < count; i++)
+		order[i] = i;
+
+	i915_random_reorder(order, count, state);
+	return order;
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_random.h b/drivers/gpu/drm/i915/selftests/i915_random.h
new file mode 100644
index 000000000000..bc8a48d4172c
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_random.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __I915_SELFTESTS_RANDOM_H__
+#define __I915_SELFTESTS_RANDOM_H__
+
+#include <linux/random.h>
+
+#include "i915_selftest.h"
+
+#define I915_RND_STATE_INITIALIZER() ({					\
+	struct rnd_state state__;					\
+	prandom_seed_state(&state__, i915_selftest.random_seed);	\
+	state__;							\
+})
+
+#define I915_RND_STATE(name__) \
+	struct rnd_state name__ = I915_RND_STATE_INITIALIZER()
+
+unsigned int *i915_random_order(unsigned int count,
+				struct rnd_state *state);
+void i915_random_reorder(unsigned int *order,
+			 unsigned int count,
+			 struct rnd_state *state);
+
+#endif /* !__I915_SELFTESTS_RANDOM_H__ */
diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
new file mode 100644
index 000000000000..f3c64412ed56
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_random.h"
+#include "i915_selftest.h"
+
+#include "mock_engine.h"
+
+static int check_rbtree(struct intel_engine_cs *engine,
+			const unsigned long *bitmap,
+			const struct intel_wait *waiters,
+			const int count)
+{
+	struct intel_breadcrumbs *b = &engine->breadcrumbs;
+	struct rb_node *rb;
+	int n;
+
+	if (&b->first_wait->node != rb_first(&b->waiters)) {
+		pr_err("First waiter does not match first element of wait-tree\n");
+		return -EINVAL;
+	}
+
+	n = find_first_bit(bitmap, count);
+	for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
+		struct intel_wait *w = container_of(rb, typeof(*w), node);
+		int idx = w - waiters;
+
+		if (!test_bit(idx, bitmap)) {
+			pr_err("waiter[%d, seqno=%d] removed but still in wait-tree\n",
+			       idx, w->seqno);
+			return -EINVAL;
+		}
+
+		if (n != idx) {
+			pr_err("waiter[%d, seqno=%d] does not match expected next element in tree [%d]\n",
+			       idx, w->seqno, n);
+			return -EINVAL;
+		}
+
+		n = find_next_bit(bitmap, count, n + 1);
+	}
+
+	return 0;
+}
+
+static int check_rbtree_empty(struct intel_engine_cs *engine)
+{
+	struct intel_breadcrumbs *b = &engine->breadcrumbs;
+
+	if (b->first_wait) {
+		pr_err("Empty breadcrumbs still has a waiter\n");
+		return -EINVAL;
+	}
+
+	if (!RB_EMPTY_ROOT(&b->waiters)) {
+		pr_err("Empty breadcrumbs, but wait-tree not empty\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int igt_random_insert_remove(void *arg)
+{
+	const u32 seqno_bias = 0x1000;
+	I915_RND_STATE(prng);
+	struct intel_engine_cs *engine = arg;
+	struct intel_wait *waiters;
+	const int count = 4096;
+	int *in_order, *out_order;
+	unsigned long *bitmap;
+	int err = -ENOMEM;
+	int n;
+
+	mock_engine_reset(engine);
+
+	waiters = drm_malloc_gfp(count, sizeof(*waiters), GFP_TEMPORARY);
+	if (!waiters)
+		goto out_engines;
+
+	bitmap = kcalloc(DIV_ROUND_UP(count, BITS_PER_LONG), sizeof(*bitmap),
+			 GFP_TEMPORARY);
+	if (!bitmap)
+		goto out_waiters;
+
+	in_order = i915_random_order(count, &prng);
+	if (!in_order)
+		goto out_bitmap;
+
+	out_order = i915_random_order(count, &prng);
+	if (!out_order)
+		goto out_order;
+
+	for (n = 0; n < count; n++)
+		intel_wait_init(&waiters[n], seqno_bias + n);
+
+	err = check_rbtree(engine, bitmap, waiters, count);
+	if (err)
+		goto err;
+
+	for (n = 0; n < count; n++) {
+		int i = in_order[n];
+
+		intel_engine_add_wait(engine, &waiters[i]);
+		__set_bit(i, bitmap);
+
+		err = check_rbtree(engine, bitmap, waiters, count);
+		if (err)
+			goto err;
+	}
+	for (n = 0; n < count; n++) {
+		int i = out_order[n];
+
+		intel_engine_remove_wait(engine, &waiters[i]);
+		__clear_bit(i, bitmap);
+
+		err = check_rbtree(engine, bitmap, waiters, count);
+		if (err)
+			goto err;
+	}
+
+	err = check_rbtree_empty(engine);
+err:
+	kfree(out_order);
+out_order:
+	kfree(in_order);
+out_bitmap:
+	kfree(bitmap);
+out_waiters:
+	drm_free_large(waiters);
+out_engines:
+	mock_engine_flush(engine);
+	return err;
+}
+
+int intel_breadcrumbs_selftest(void)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_random_insert_remove),
+	};
+	struct intel_engine_cs *engine;
+	int err;
+
+	engine = mock_engine("mock");
+	if (!engine)
+		return -ENOMEM;
+
+	err = i915_subtests(tests, engine);
+	kfree(engine);
+
+	return err;
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c
new file mode 100644
index 000000000000..085d611ed56b
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_engine.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "mock_engine.h"
+
+struct intel_engine_cs *mock_engine(const char *name)
+{
+	struct intel_engine_cs *engine;
+	static int id;
+
+	engine = kzalloc(sizeof(*engine) + PAGE_SIZE, GFP_TEMPORARY);
+	if (!engine)
+		return NULL;
+
+	/* minimal engine setup for seqno */
+	engine->name = name;
+	engine->id = id++;
+	engine->status_page.page_addr = (void *)(engine + 1);
+
+	/* minimal breadcrumbs init */
+	spin_lock_init(&engine->breadcrumbs.lock);
+	engine->breadcrumbs.mock = true;
+
+	return engine;
+}
+
+void mock_engine_flush(struct intel_engine_cs *engine)
+{
+}
+
+void mock_engine_reset(struct intel_engine_cs *engine)
+{
+	intel_write_status_page(engine, I915_GEM_HWS_INDEX, 0);
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.h b/drivers/gpu/drm/i915/selftests/mock_engine.h
new file mode 100644
index 000000000000..0ae9a94aaa1e
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_engine.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __MOCK_ENGINE_H__
+#define __MOCK_ENGINE_H__
+
+struct intel_engine_cs *mock_engine(const char *name);
+void mock_engine_flush(struct intel_engine_cs *engine);
+void mock_engine_reset(struct intel_engine_cs *engine);
+
+#endif /* !__MOCK_ENGINE_H__ */
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 05/19] drm/i915: Add unit tests for the breadcrumb rbtree, completion
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (2 preceding siblings ...)
  2016-12-20 13:07 ` [RFCv2 04/19] drm/i915: Add unit tests for the breadcrumb rbtree, insert/remove Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 06/19] drm/i915: Add unit tests for the breadcrumb rbtree, wakeups Chris Wilson
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Second retroactive test, make sure that the waiters are removed from the
global wait-tree when their seqno completes.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 103 +++++++++++++++++++++
 drivers/gpu/drm/i915/selftests/mock_engine.h       |   6 ++
 2 files changed, 109 insertions(+)

diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
index f3c64412ed56..cbc8a8456d59 100644
--- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
@@ -64,6 +64,27 @@ static int check_rbtree(struct intel_engine_cs *engine,
 	return 0;
 }
 
+static int check_completion(struct intel_engine_cs *engine,
+			    const unsigned long *bitmap,
+			    const struct intel_wait *waiters,
+			    const int count)
+{
+	int n;
+
+	for (n = 0; n < count; n++) {
+		if (intel_wait_complete(&waiters[n]) != !!test_bit(n, bitmap))
+			continue;
+
+		pr_err("waiter[%d, seqno=%d] is %s, but expected %s\n",
+		       n, waiters[n].seqno,
+		       intel_wait_complete(&waiters[n]) ? "complete" : "active",
+		       test_bit(n, bitmap) ? "active" : "complete");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int check_rbtree_empty(struct intel_engine_cs *engine)
 {
 	struct intel_breadcrumbs *b = &engine->breadcrumbs;
@@ -154,10 +175,92 @@ static int igt_random_insert_remove(void *arg)
 	return err;
 }
 
+static int igt_insert_complete(void *arg)
+{
+	const u32 seqno_bias = 0x1000;
+	struct intel_engine_cs *engine = arg;
+	struct intel_wait *waiters;
+	const int count = 4096;
+	unsigned long *bitmap;
+	int err = -ENOMEM;
+	int n, m;
+
+	mock_engine_reset(engine);
+
+	waiters = drm_malloc_gfp(count, sizeof(*waiters), GFP_TEMPORARY);
+	if (!waiters)
+		goto out_engines;
+
+	bitmap = kcalloc(DIV_ROUND_UP(count, BITS_PER_LONG), sizeof(*bitmap),
+			 GFP_TEMPORARY);
+	if (!bitmap)
+		goto out_waiters;
+
+	for (n = 0; n < count; n++) {
+		intel_wait_init(&waiters[n], n + seqno_bias);
+		intel_engine_add_wait(engine, &waiters[n]);
+		__set_bit(n, bitmap);
+	}
+	err = check_rbtree(engine, bitmap, waiters, count);
+	if (err)
+		goto err;
+
+	for (n = 0; n < count; n = m) {
+		int seqno = 2 * n;
+
+		GEM_BUG_ON(find_first_bit(bitmap, count) != n);
+
+		if (intel_wait_complete(&waiters[n])) {
+			pr_err("waiter[%d, seqno=%d] completed too early\n",
+			       n, waiters[n].seqno);
+			err = -EINVAL;
+			goto err;
+		}
+
+		/* complete the following waiters */
+		mock_seqno_advance(engine, seqno + seqno_bias);
+		for (m = n; m <= seqno; m++) {
+			if (m == count)
+				break;
+
+			GEM_BUG_ON(!test_bit(m, bitmap));
+			__clear_bit(m, bitmap);
+		}
+
+		intel_engine_remove_wait(engine, &waiters[n]);
+		RB_CLEAR_NODE(&waiters[n].node);
+
+		err = check_rbtree(engine, bitmap, waiters, count);
+		if (err) {
+			pr_err("rbtree corrupt after seqno advance to %d\n",
+			       seqno + seqno_bias);
+			goto err;
+		}
+
+		err = check_completion(engine, bitmap, waiters, count);
+		if (err) {
+			pr_err("completions after seqno advance to %d failed\n",
+			       seqno + seqno_bias);
+			goto err;
+		}
+	}
+
+	err = check_rbtree_empty(engine);
+err:
+	kfree(bitmap);
+out_waiters:
+	drm_free_large(waiters);
+out_engines:
+	mock_engine_flush(engine);
+out:
+	return err;
+}
+
 int intel_breadcrumbs_selftest(void)
 {
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_random_insert_remove),
+		SUBTEST(igt_insert_complete),
 	};
 	struct intel_engine_cs *engine;
 	int err;
diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.h b/drivers/gpu/drm/i915/selftests/mock_engine.h
index 0ae9a94aaa1e..9cfe9671f860 100644
--- a/drivers/gpu/drm/i915/selftests/mock_engine.h
+++ b/drivers/gpu/drm/i915/selftests/mock_engine.h
@@ -29,4 +29,10 @@ struct intel_engine_cs *mock_engine(const char *name);
 void mock_engine_flush(struct intel_engine_cs *engine);
 void mock_engine_reset(struct intel_engine_cs *engine);
 
+static inline void mock_seqno_advance(struct intel_engine_cs *engine, u32 seqno)
+{
+	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
+	intel_engine_wakeup(engine);
+}
+
 #endif /* !__MOCK_ENGINE_H__ */
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 06/19] drm/i915: Add unit tests for the breadcrumb rbtree, wakeups
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (3 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 05/19] drm/i915: Add unit tests for the breadcrumb rbtree, completion Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 07/19] drm/i915: Mock the GEM device for self-testing Chris Wilson
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Third retroactive test, make sure that the seqno waiters are woken.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c | 169 ++++++++++++++++++++-
 1 file changed, 168 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
index cbc8a8456d59..19859379d7d5 100644
--- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
@@ -252,7 +252,173 @@ static int igt_insert_complete(void *arg)
 	drm_free_large(waiters);
 out_engines:
 	mock_engine_flush(engine);
-out:
+	return err;
+}
+
+struct igt_wakeup {
+	struct task_struct *tsk;
+	atomic_t *ready, *set, *done;
+	struct intel_engine_cs *engine;
+	unsigned long flags;
+	wait_queue_head_t *wq;
+	u32 seqno;
+};
+
+static int wait_atomic(atomic_t *p)
+{
+	schedule();
+	return 0;
+}
+
+static int wait_atomic_timeout(atomic_t *p)
+{
+	return schedule_timeout(10 * HZ) ? 0 : -ETIMEDOUT;
+}
+
+static int igt_wakeup_thread(void *arg)
+{
+	struct igt_wakeup *w = arg;
+	struct intel_wait wait;
+
+	while (!kthread_should_stop()) {
+		DEFINE_WAIT(ready);
+
+		for (;;) {
+			prepare_to_wait(w->wq, &ready, TASK_INTERRUPTIBLE);
+			if (atomic_read(w->ready) == 0)
+				break;
+
+			schedule();
+		}
+		finish_wait(w->wq, &ready);
+		if (atomic_dec_and_test(w->set))
+			wake_up_atomic_t(w->set);
+
+		if (test_bit(0, &w->flags))
+			break;
+
+		intel_wait_init(&wait, w->seqno);
+		intel_engine_add_wait(w->engine, &wait);
+		for (;;) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			if (i915_seqno_passed(intel_engine_get_seqno(w->engine),
+					      w->seqno))
+				break;
+
+			schedule();
+		}
+		intel_engine_remove_wait(w->engine, &wait);
+		__set_current_state(TASK_RUNNING);
+
+		if (atomic_dec_and_test(w->done))
+			wake_up_atomic_t(w->done);
+	}
+
+	if (atomic_dec_and_test(w->done))
+		wake_up_atomic_t(w->done);
+	return 0;
+}
+
+static void igt_wake_all_sync(atomic_t *ready,
+			      atomic_t *set,
+			      atomic_t *done,
+			      wait_queue_head_t *wq,
+			      int count)
+{
+	atomic_set(set, count);
+	atomic_set(done, count);
+
+	atomic_set(ready, 0);
+	wake_up_all(wq);
+
+	wait_on_atomic_t(set, wait_atomic, TASK_UNINTERRUPTIBLE);
+	atomic_set(ready, count);
+}
+
+static int igt_wakeup(void *arg)
+{
+	const int state = TASK_UNINTERRUPTIBLE;
+	struct intel_engine_cs *engine = arg;
+	struct igt_wakeup *waiters;
+	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+	const int count = 4096;
+	const u32 max_seqno = count / 4;
+	atomic_t ready, set, done;
+	int err = -ENOMEM;
+	int n, step;
+
+	mock_engine_reset(engine);
+
+	waiters = drm_malloc_gfp(count, sizeof(*waiters), GFP_TEMPORARY);
+	if (!waiters)
+		goto out_engines;
+
+	atomic_set(&ready, count);
+	for (n = 0; n < count; n++) {
+		waiters[n].wq = &wq;
+		waiters[n].ready = &ready;
+		waiters[n].set = &set;
+		waiters[n].done = &done;
+		waiters[n].engine = engine;
+		waiters[n].flags = 0;
+
+		waiters[n].tsk = kthread_run(igt_wakeup_thread, &waiters[n],
+					     "i915/igt:%d", n);
+		if (IS_ERR(waiters[n].tsk))
+			goto out_waiters;
+
+		get_task_struct(waiters[n].tsk);
+	}
+
+	for (step = 1; step <= max_seqno; step <<= 1) {
+		u32 seqno;
+
+		for (n = 0; n < count; n++)
+			waiters[n].seqno = 1 + get_random_int() % max_seqno;
+
+		mock_seqno_advance(engine, 0);
+		igt_wake_all_sync(&ready, &set, &done, &wq, count);
+
+		for (seqno = 1; seqno <= max_seqno + step; seqno += step) {
+			usleep_range(50, 500);
+			mock_seqno_advance(engine, seqno);
+		}
+		GEM_BUG_ON(intel_engine_get_seqno(engine) < 1 + max_seqno);
+
+		err = wait_on_atomic_t(&done, wait_atomic_timeout, state);
+		if (err) {
+			pr_err("Timed out waiting for %d remaining waiters\n",
+			       atomic_read(&done));
+			break;
+		}
+
+		err = check_rbtree_empty(engine);
+		if (err)
+			break;
+	}
+
+out_waiters:
+	for (n = 0; n < count; n++) {
+		if (IS_ERR(waiters[n].tsk))
+			break;
+
+		set_bit(0, &waiters[n].flags);
+	}
+
+	igt_wake_all_sync(&ready, &set, &done, &wq, n);
+	wait_on_atomic_t(&done, wait_atomic, state);
+
+	for (n = 0; n < count; n++) {
+		if (IS_ERR(waiters[n].tsk))
+			break;
+
+		kthread_stop(waiters[n].tsk);
+		put_task_struct(waiters[n].tsk);
+	}
+
+	drm_free_large(waiters);
+out_engines:
+	mock_engine_flush(engine);
 	return err;
 }
 
@@ -261,6 +427,7 @@ int intel_breadcrumbs_selftest(void)
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_random_insert_remove),
 		SUBTEST(igt_insert_complete),
+		SUBTEST(igt_wakeup),
 	};
 	struct intel_engine_cs *engine;
 	int err;
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 07/19] drm/i915: Mock the GEM device for self-testing
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (4 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 06/19] drm/i915: Add unit tests for the breadcrumb rbtree, wakeups Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-09 15:10   ` Matthew Auld
  2016-12-20 13:08 ` [RFCv2 08/19] drm/i915: Mock a GGTT " Chris Wilson
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem.c                  |   1 +
 drivers/gpu/drm/i915/selftests/mock_gem_device.c | 109 +++++++++++++++++++++++
 drivers/gpu/drm/i915/selftests/mock_gem_device.h |   8 ++
 drivers/gpu/drm/i915/selftests/mock_gem_object.h |   8 ++
 4 files changed, 126 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_device.c
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_device.h
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_object.h

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4547d4cd2064..f52f1aafb4b9 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4976,4 +4976,5 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
 
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/scatterlist.c"
+#include "selftests/mock_gem_device.c"
 #endif
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
new file mode 100644
index 000000000000..95cf1d845bf1
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/pm_runtime.h>
+
+#include "mock_gem_device.h"
+#include "mock_gem_object.h"
+
+static void mock_device_release(struct drm_device *dev)
+{
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	rcu_barrier();
+	while (flush_work(&i915->mm.free_work))
+		rcu_barrier();
+
+	kmem_cache_destroy(i915->objects);
+	put_device(&i915->drm.pdev->dev);
+}
+
+static struct drm_driver mock_driver = {
+	.name = "mock",
+	.driver_features = DRIVER_GEM,
+	.release = mock_device_release,
+
+	.gem_close_object = i915_gem_close_object,
+	.gem_free_object_unlocked = i915_gem_free_object,
+};
+
+static void release_dev(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	kfree(pdev);
+}
+
+struct drm_i915_private *mock_gem_device(void)
+{
+	struct drm_i915_private *i915;
+	struct pci_dev *pdev;
+	int err;
+
+	i915 = kzalloc(sizeof(*i915), GFP_TEMPORARY);
+	if (!i915)
+		return NULL;
+
+	pdev = kzalloc(sizeof(*pdev), GFP_TEMPORARY);
+	if (!pdev) {
+		kfree(i915);
+		return NULL;
+	}
+
+	device_initialize(&pdev->dev);
+	pdev->dev.release = release_dev;
+	dev_set_name(&pdev->dev, "mock");
+	dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
+	pci_set_drvdata(pdev, i915);
+
+	err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev);
+	if (err) {
+		pr_err("Failed to initialise mock GEM device: err=%d\n", err);
+		put_device(&pdev->dev);
+		kfree(i915);
+		return NULL;
+	}
+	i915->drm.pdev = pdev;
+	i915->drm.dev_private = i915;
+
+	mkwrite_device_info(i915)->gen = -1;
+
+	spin_lock_init(&i915->mm.object_stat_lock);
+
+	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
+	init_llist_head(&i915->mm.free_list);
+
+	i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN);
+	if (!i915->objects)
+		goto err_device;
+
+	return i915;
+
+err_device:
+	kfree(i915);
+	return NULL;
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.h b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
new file mode 100644
index 000000000000..7ff7c848f731
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
@@ -0,0 +1,8 @@
+#ifndef __MOCK_GEM_DEVICE_H__
+#define __MOCK_GEM_DEVICE_H__
+
+#include "i915_drv.h"
+
+struct drm_i915_private *mock_gem_device(void);
+
+#endif /* !__MOCK_GEM_DEVICE_H__ */
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_object.h b/drivers/gpu/drm/i915/selftests/mock_gem_object.h
new file mode 100644
index 000000000000..9fbf67321662
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_object.h
@@ -0,0 +1,8 @@
+#ifndef __MOCK_GEM_OBJECT_H__
+#define __MOCK_GEM_OBJECT_H__
+
+struct mock_object {
+	struct drm_i915_gem_object base;
+};
+
+#endif /* !__MOCK_GEM_OBJECT_H__ */
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 08/19] drm/i915: Mock a GGTT for self-testing
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (5 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 07/19] drm/i915: Mock the GEM device for self-testing Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-09 15:16   ` Matthew Auld
  2016-12-20 13:08 ` [RFCv2 09/19] drm/i915: Mock infrastructure for request emission Chris Wilson
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

A very simple mockery, just a random manager and timeline. Useful for
inserting objects and ordering retirement; and not much else.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c              |  4 ++
 drivers/gpu/drm/i915/selftests/mock_gem_device.c | 22 +++++++
 drivers/gpu/drm/i915/selftests/mock_gem_device.h |  1 +
 drivers/gpu/drm/i915/selftests/mock_ggtt.c       | 79 ++++++++++++++++++++++++
 4 files changed, 106 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_ggtt.c

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index d35c46b477a6..5a98e2ca5a53 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3576,3 +3576,7 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
 					   size, alignment, colour,
 					   start, end, DRM_MM_INSERT_EVICT);
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/mock_ggtt.c"
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index 95cf1d845bf1..025012ba92eb 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -35,6 +35,7 @@ static void mock_device_release(struct drm_device *dev)
 	while (flush_work(&i915->mm.free_work))
 		rcu_barrier();
 
+	kmem_cache_destroy(i915->vmas);
 	kmem_cache_destroy(i915->objects);
 	put_device(&i915->drm.pdev->dev);
 }
@@ -90,19 +91,40 @@ struct drm_i915_private *mock_gem_device(void)
 	i915->drm.pdev = pdev;
 	i915->drm.dev_private = i915;
 
+	drm_mode_config_init(&i915->drm);
+
 	mkwrite_device_info(i915)->gen = -1;
 
 	spin_lock_init(&i915->mm.object_stat_lock);
 
 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
 	init_llist_head(&i915->mm.free_list);
+	INIT_LIST_HEAD(&i915->mm.unbound_list);
+	INIT_LIST_HEAD(&i915->mm.bound_list);
 
 	i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN);
 	if (!i915->objects)
 		goto err_device;
 
+	i915->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
+	if (!i915->vmas)
+		goto err_objects;
+
+	mutex_lock(&i915->drm.struct_mutex);
+	INIT_LIST_HEAD(&i915->gt.timelines);
+	err = i915_gem_timeline_init__global(i915);
+	if (err)
+		goto err_vmas;
+
+	mock_init_ggtt(i915);
+	mutex_unlock(&i915->drm.struct_mutex);
+
 	return i915;
 
+err_vmas:
+	kmem_cache_destroy(i915->vmas);
+err_objects:
+	kmem_cache_destroy(i915->objects);
 err_device:
 	kfree(i915);
 	return NULL;
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.h b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
index 7ff7c848f731..5189f684a17e 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.h
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
@@ -4,5 +4,6 @@
 #include "i915_drv.h"
 
 struct drm_i915_private *mock_gem_device(void);
+void mock_init_ggtt(struct drm_i915_private *i915);
 
 #endif /* !__MOCK_GEM_DEVICE_H__ */
diff --git a/drivers/gpu/drm/i915/selftests/mock_ggtt.c b/drivers/gpu/drm/i915/selftests/mock_ggtt.c
new file mode 100644
index 000000000000..d5f2811bc220
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_ggtt.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "mock_gem_device.h"
+
+static void mock_insert_page(struct i915_address_space *vm,
+			     dma_addr_t addr,
+			     uint64_t offset,
+			     enum i915_cache_level level,
+			     u32 flags)
+{
+}
+
+static void mock_insert_entries(struct i915_address_space *vm,
+				struct sg_table *st,
+				uint64_t start,
+				enum i915_cache_level level, u32 flags)
+{
+}
+
+static int mock_bind_vma(struct i915_vma *vma,
+			 enum i915_cache_level cache_level,
+			 u32 flags)
+{
+	vma->pages = vma->obj->mm.pages;
+	vma->flags |= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
+	return 0;
+}
+
+static void mock_unbind_vma(struct i915_vma *vma)
+{
+}
+
+static void mock_remove(struct i915_address_space *vm)
+{
+}
+
+void mock_init_ggtt(struct drm_i915_private *i915)
+{
+	struct i915_ggtt *ggtt = &i915->ggtt;
+
+	INIT_LIST_HEAD(&i915->vm_list);
+
+	ggtt->base.i915 = i915;
+
+	ggtt->mappable_base = 0;
+	ggtt->mappable_end = 2048 * PAGE_SIZE;
+	ggtt->base.total = 4096 * PAGE_SIZE;
+
+	ggtt->base.clear_range = nop_clear_range;
+	ggtt->base.insert_page = mock_insert_page;
+	ggtt->base.insert_entries = mock_insert_entries;
+	ggtt->base.bind_vma = mock_bind_vma;
+	ggtt->base.unbind_vma = mock_unbind_vma;
+	ggtt->base.cleanup = mock_remove;
+
+	i915_address_space_init(&ggtt->base, i915, "global");
+}
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 09/19] drm/i915: Mock infrastructure for request emission
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (6 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 08/19] drm/i915: Mock a GGTT " Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 10/19] drm/i915: Add selftests for i915_gem_request Chris Wilson
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_context.c            |   4 +
 drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c |  11 +-
 drivers/gpu/drm/i915/selftests/mock_context.c      |  95 ++++++++++++
 drivers/gpu/drm/i915/selftests/mock_context.h      |  34 +++++
 drivers/gpu/drm/i915/selftests/mock_engine.c       | 161 +++++++++++++++++++--
 drivers/gpu/drm/i915/selftests/mock_engine.h       |  18 ++-
 drivers/gpu/drm/i915/selftests/mock_gem_device.c   | 100 ++++++++++++-
 drivers/gpu/drm/i915/selftests/mock_gem_device.h   |   2 +
 drivers/gpu/drm/i915/selftests/mock_request.c      |  45 ++++++
 drivers/gpu/drm/i915/selftests/mock_request.h      |  44 ++++++
 10 files changed, 496 insertions(+), 18 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_context.c
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_context.h
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_request.c
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_request.h

diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 15b25c1b1f4d..a4e5515c4ef3 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -1138,3 +1138,7 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
 
 	return 0;
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/mock_context.c"
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
index 19859379d7d5..535949d518aa 100644
--- a/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/selftests/intel_breadcrumbs.c
@@ -25,6 +25,7 @@
 #include "i915_random.h"
 #include "i915_selftest.h"
 
+#include "mock_gem_device.h"
 #include "mock_engine.h"
 
 static int check_rbtree(struct intel_engine_cs *engine,
@@ -429,15 +430,15 @@ int intel_breadcrumbs_selftest(void)
 		SUBTEST(igt_insert_complete),
 		SUBTEST(igt_wakeup),
 	};
-	struct intel_engine_cs *engine;
+	struct drm_i915_private *i915;
 	int err;
 
-	engine = mock_engine("mock");
-	if (!engine)
+	i915 = mock_gem_device();
+	if (!i915)
 		return -ENOMEM;
 
-	err = i915_subtests(tests, engine);
-	kfree(engine);
+	err = i915_subtests(tests, i915->engine[RCS]);
+	drm_dev_unref(&i915->drm);
 
 	return err;
 }
diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c
new file mode 100644
index 000000000000..e808898bd22d
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_context.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "mock_context.h"
+
+static void mock_ppgtt_cleanup(struct i915_address_space *vm)
+{
+}
+
+static struct i915_hw_ppgtt *
+mock_ppgtt(struct drm_i915_private *i915,
+	   const char *name)
+{
+	struct i915_hw_ppgtt *ppgtt;
+
+	ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
+	if (!ppgtt)
+		return NULL;
+
+	kref_init(&ppgtt->ref);
+
+	INIT_LIST_HEAD(&ppgtt->base.active_list);
+	INIT_LIST_HEAD(&ppgtt->base.inactive_list);
+	INIT_LIST_HEAD(&ppgtt->base.unbound_list);
+
+	INIT_LIST_HEAD(&ppgtt->base.global_link);
+	drm_mm_init(&ppgtt->base.mm, 0, ~0);
+	i915_gem_timeline_init(i915, &ppgtt->base.timeline, name);
+
+	ppgtt->base.cleanup = mock_ppgtt_cleanup;
+
+	return ppgtt;
+}
+
+struct i915_gem_context *
+mock_context(struct drm_i915_private *i915,
+	     const char *name)
+{
+	struct i915_gem_context *ctx;
+	int ret;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return NULL;
+
+	kref_init(&ctx->ref);
+	INIT_LIST_HEAD(&ctx->link);
+	ctx->name = name ? kstrdup(name, GFP_KERNEL) : NULL;
+	ctx->i915 = i915;
+
+	ret = ida_simple_get(&i915->context_hw_ida,
+			     0, MAX_CONTEXT_HW_ID, GFP_KERNEL);
+	if (ret < 0) {
+		kfree(ctx);
+		return NULL;
+	}
+	ctx->hw_id = ret;
+
+	if (name) {
+		ctx->ppgtt = mock_ppgtt(i915, name);
+		if (!ctx->ppgtt) {
+			kfree(ctx);
+			return NULL;
+		}
+	}
+
+	return ctx;
+}
+
+void mock_context_close(struct i915_gem_context *ctx)
+{
+	ctx->closed = true;
+	i915_gem_context_put(ctx);
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_context.h b/drivers/gpu/drm/i915/selftests/mock_context.h
new file mode 100644
index 000000000000..2427e5c0916a
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_context.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __MOCK_CONTEXT_H
+#define __MOCK_CONTEXT_H
+
+struct i915_gem_context *
+mock_context(struct drm_i915_private *i915,
+	     const char *name);
+
+void mock_context_close(struct i915_gem_context *ctx);
+
+#endif /* !__MOCK_CONTEXT_H */
diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c
index 085d611ed56b..a9f9d6d79ac8 100644
--- a/drivers/gpu/drm/i915/selftests/mock_engine.c
+++ b/drivers/gpu/drm/i915/selftests/mock_engine.c
@@ -23,33 +23,174 @@
  */
 
 #include "mock_engine.h"
+#include "mock_request.h"
 
-struct intel_engine_cs *mock_engine(const char *name)
+static void hw_delay_complete(unsigned long data)
 {
-	struct intel_engine_cs *engine;
+	struct mock_engine *engine = (typeof(engine))data;
+	struct mock_request *request;
+
+	spin_lock(&engine->hw_lock);
+	request = list_first_entry_or_null(&engine->hw_queue,
+					   typeof(*request),
+					   link);
+	if (request) {
+		list_del(&request->link);
+		mock_seqno_advance(&engine->base, request->base.global_seqno);
+	}
+
+	request = list_first_entry_or_null(&engine->hw_queue,
+					   typeof(*request),
+					   link);
+	if (request)
+		mod_timer(&engine->hw_delay, jiffies + request->delay);
+	spin_unlock(&engine->hw_lock);
+}
+
+static int mock_context_pin(struct intel_engine_cs *engine,
+			    struct i915_gem_context *ctx)
+{
+	i915_gem_context_get(ctx);
+	return 0;
+}
+
+static void mock_context_unpin(struct intel_engine_cs *engine,
+			       struct i915_gem_context *ctx)
+{
+	i915_gem_context_put(ctx);
+}
+
+static int mock_request_alloc(struct drm_i915_gem_request *request)
+{
+	request->ring = request->engine->buffer;
+	return 0;
+}
+
+static int mock_emit_flush(struct drm_i915_gem_request *request,
+			   unsigned int flags)
+{
+	return 0;
+}
+
+static void mock_emit_breadcrumb(struct drm_i915_gem_request *request,
+				 u32 *flags)
+{
+}
+
+static void mock_submit_request(struct drm_i915_gem_request *request)
+{
+	struct mock_request *mock = container_of(request, typeof(*mock), base);
+	struct mock_engine *engine =
+		container_of(request->engine, typeof(*engine), base);
+
+	i915_gem_request_submit(request);
+
+	spin_lock_irq(&engine->hw_lock);
+	list_add_tail(&mock->link, &engine->hw_queue);
+	if (list_first_entry(&engine->hw_queue, typeof(*mock), link) == mock)
+		mod_timer(&engine->hw_delay, jiffies + mock->delay);
+	spin_unlock_irq(&engine->hw_lock);
+}
+
+static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
+{
+	const unsigned long sz = roundup_pow_of_two(sizeof(struct intel_ring));
+	struct intel_ring *ring;
+
+	ring = kzalloc(sizeof(*ring) + sz, GFP_TEMPORARY);
+	if (!ring)
+		return NULL;
+
+	ring->engine = engine;
+	ring->size = sz;
+	ring->effective_size = sz;
+	ring->vaddr = (void *)(ring + 1);
+
+	INIT_LIST_HEAD(&ring->request_list);
+	ring->last_retired_head = -1;
+	intel_ring_update_space(ring);
+
+	return ring;
+}
+
+struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
+				    const char *name)
+{
+	struct mock_engine *engine;
 	static int id;
 
 	engine = kzalloc(sizeof(*engine) + PAGE_SIZE, GFP_TEMPORARY);
 	if (!engine)
 		return NULL;
 
-	/* minimal engine setup for seqno */
-	engine->name = name;
-	engine->id = id++;
-	engine->status_page.page_addr = (void *)(engine + 1);
+	engine->base.buffer = mock_ring(&engine->base);
+	if (!engine->base.buffer) {
+		kfree(engine);
+		return NULL;
+	}
+
+	/* minimal engine setup for requests */
+	engine->base.i915 = i915;
+	engine->base.name = name;
+	engine->base.id = id++;
+	engine->base.status_page.page_addr = (void *)(engine + 1);
+
+	engine->base.context_pin = mock_context_pin;
+	engine->base.context_unpin = mock_context_unpin;
+	engine->base.request_alloc = mock_request_alloc;
+	engine->base.emit_flush = mock_emit_flush;
+	engine->base.emit_breadcrumb = mock_emit_breadcrumb;
+	engine->base.submit_request = mock_submit_request;
 
-	/* minimal breadcrumbs init */
-	spin_lock_init(&engine->breadcrumbs.lock);
-	engine->breadcrumbs.mock = true;
+	engine->base.timeline =
+		&i915->gt.global_timeline.engine[engine->base.id];
 
-	return engine;
+	intel_engine_init_breadcrumbs(&engine->base);
+	engine->base.breadcrumbs.mock = true; /* prevent touching HW for irqs */
+
+	/* fake hw queue */
+	spin_lock_init(&engine->hw_lock);
+	setup_timer(&engine->hw_delay,
+		    hw_delay_complete,
+		    (unsigned long)engine);
+	INIT_LIST_HEAD(&engine->hw_queue);
+
+	return &engine->base;
 }
 
 void mock_engine_flush(struct intel_engine_cs *engine)
 {
+	struct mock_engine *mock =
+		container_of(engine, typeof(*mock), base);
+	struct mock_request *request, *rn;
+
+	del_timer_sync(&mock->hw_delay);
+
+	spin_lock_irq(&mock->hw_lock);
+	list_for_each_entry_safe(request, rn, &mock->hw_queue, link) {
+		list_del_init(&request->link);
+		mock_seqno_advance(&mock->base, request->base.global_seqno);
+	}
+	spin_unlock_irq(&mock->hw_lock);
 }
 
 void mock_engine_reset(struct intel_engine_cs *engine)
 {
 	intel_write_status_page(engine, I915_GEM_HWS_INDEX, 0);
 }
+
+void mock_engine_free(struct intel_engine_cs *engine)
+{
+	struct mock_engine *mock =
+		container_of(engine, typeof(*mock), base);
+
+	GEM_BUG_ON(timer_pending(&mock->hw_delay));
+
+	if (engine->last_retired_context)
+		engine->context_unpin(engine, engine->last_retired_context);
+
+	intel_engine_fini_breadcrumbs(engine);
+
+	kfree(engine->buffer);
+	kfree(engine);
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.h b/drivers/gpu/drm/i915/selftests/mock_engine.h
index 9cfe9671f860..d080d0a10a4f 100644
--- a/drivers/gpu/drm/i915/selftests/mock_engine.h
+++ b/drivers/gpu/drm/i915/selftests/mock_engine.h
@@ -25,9 +25,25 @@
 #ifndef __MOCK_ENGINE_H__
 #define __MOCK_ENGINE_H__
 
-struct intel_engine_cs *mock_engine(const char *name);
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+
+#include "intel_ringbuffer.h"
+
+struct mock_engine {
+	struct intel_engine_cs base;
+
+	spinlock_t hw_lock;
+	struct list_head hw_queue;
+	struct timer_list hw_delay;
+};
+
+struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
+				    const char *name);
 void mock_engine_flush(struct intel_engine_cs *engine);
 void mock_engine_reset(struct intel_engine_cs *engine);
+void mock_engine_free(struct intel_engine_cs *engine);
 
 static inline void mock_seqno_advance(struct intel_engine_cs *engine, u32 seqno)
 {
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index 025012ba92eb..a146390c47df 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -24,17 +24,58 @@
 
 #include <linux/pm_runtime.h>
 
+#include "mock_engine.h"
+#include "mock_context.h"
+#include "mock_request.h"
 #include "mock_gem_device.h"
 #include "mock_gem_object.h"
 
+void mock_device_flush(struct drm_i915_private *i915)
+{
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	lockdep_assert_held(&i915->drm.struct_mutex);
+
+	for_each_engine(engine, i915, id)
+		mock_engine_flush(engine);
+
+	i915_gem_retire_requests(i915);
+}
+
 static void mock_device_release(struct drm_device *dev)
 {
 	struct drm_i915_private *i915 = to_i915(dev);
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	mutex_lock(&i915->drm.struct_mutex);
+	mock_device_flush(i915);
+	mutex_unlock(&i915->drm.struct_mutex);
+
+	cancel_delayed_work_sync(&i915->gt.retire_work);
+	cancel_delayed_work_sync(&i915->gt.idle_work);
+
+	mutex_lock(&i915->drm.struct_mutex);
+	for_each_engine(engine, i915, id)
+		mock_engine_free(engine);
+
+	i915_gem_context_fini(i915);
+
+	i915_gem_timeline_fini(&i915->ggtt.base.timeline);
+	i915_gem_timeline_fini(&i915->gt.global_timeline);
+	mutex_unlock(&i915->drm.struct_mutex);
+
+	drain_workqueue(i915->wq);
 
 	rcu_barrier();
 	while (flush_work(&i915->mm.free_work))
 		rcu_barrier();
 
+	destroy_workqueue(i915->wq);
+
+	kmem_cache_destroy(i915->dependencies);
+	kmem_cache_destroy(i915->requests);
 	kmem_cache_destroy(i915->vmas);
 	kmem_cache_destroy(i915->objects);
 	put_device(&i915->drm.pdev->dev);
@@ -56,9 +97,19 @@ static void release_dev(struct device *dev)
 	kfree(pdev);
 }
 
+static void mock_retire_work_handler(struct work_struct *work)
+{
+}
+
+static void mock_idle_work_handler(struct work_struct *work)
+{
+}
+
 struct drm_i915_private *mock_gem_device(void)
 {
 	struct drm_i915_private *i915;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	struct pci_dev *pdev;
 	int err;
 
@@ -97,34 +148,79 @@ struct drm_i915_private *mock_gem_device(void)
 
 	spin_lock_init(&i915->mm.object_stat_lock);
 
+	init_waitqueue_head(&i915->gpu_error.wait_queue);
+	init_waitqueue_head(&i915->gpu_error.reset_queue);
+
+	i915->wq = alloc_ordered_workqueue("mock", 0);
+	if (!i915->wq)
+		goto err_device;
+
 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
 	init_llist_head(&i915->mm.free_list);
 	INIT_LIST_HEAD(&i915->mm.unbound_list);
 	INIT_LIST_HEAD(&i915->mm.bound_list);
 
+	ida_init(&i915->context_hw_ida);
+
+	INIT_DELAYED_WORK(&i915->gt.retire_work, mock_retire_work_handler);
+	INIT_DELAYED_WORK(&i915->gt.idle_work, mock_idle_work_handler);
+
+	i915->gt.awake = true;
+
 	i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN);
 	if (!i915->objects)
-		goto err_device;
+		goto err_wq;
 
 	i915->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
 	if (!i915->vmas)
 		goto err_objects;
 
+	i915->requests = KMEM_CACHE(mock_request,
+				    SLAB_HWCACHE_ALIGN |
+				    SLAB_RECLAIM_ACCOUNT |
+				    SLAB_DESTROY_BY_RCU);
+	if (!i915->requests)
+		goto err_vmas;
+
+	i915->dependencies = KMEM_CACHE(i915_dependency,
+					SLAB_HWCACHE_ALIGN |
+					SLAB_RECLAIM_ACCOUNT);
+	if (!i915->dependencies)
+		goto err_requests;
+
 	mutex_lock(&i915->drm.struct_mutex);
 	INIT_LIST_HEAD(&i915->gt.timelines);
 	err = i915_gem_timeline_init__global(i915);
 	if (err)
-		goto err_vmas;
+		goto err_dependencies;
 
 	mock_init_ggtt(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 
+	mkwrite_device_info(i915)->ring_mask = BIT(0);
+	i915->engine[RCS] = mock_engine(i915, "mock");
+	if (!i915->engine[RCS])
+		goto err_dependencies;
+
+	i915->kernel_context = mock_context(i915, NULL);
+	if (!i915->kernel_context)
+		goto err_engine;
+
 	return i915;
 
+err_engine:
+	for_each_engine(engine, i915, id)
+		mock_engine_free(engine);
+err_dependencies:
+	kmem_cache_destroy(i915->dependencies);
+err_requests:
+	kmem_cache_destroy(i915->requests);
 err_vmas:
 	kmem_cache_destroy(i915->vmas);
 err_objects:
 	kmem_cache_destroy(i915->objects);
+err_wq:
+	destroy_workqueue(i915->wq);
 err_device:
 	kfree(i915);
 	return NULL;
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.h b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
index 5189f684a17e..9047d9068122 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.h
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
@@ -4,6 +4,8 @@
 #include "i915_drv.h"
 
 struct drm_i915_private *mock_gem_device(void);
+void mock_device_flush(struct drm_i915_private *i915);
+
 void mock_init_ggtt(struct drm_i915_private *i915);
 
 #endif /* !__MOCK_GEM_DEVICE_H__ */
diff --git a/drivers/gpu/drm/i915/selftests/mock_request.c b/drivers/gpu/drm/i915/selftests/mock_request.c
new file mode 100644
index 000000000000..bdba38fda108
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_request.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "mock_request.h"
+
+struct drm_i915_gem_request *
+mock_request(struct intel_engine_cs *engine,
+	     struct i915_gem_context *context,
+	     unsigned long delay)
+{
+	struct drm_i915_gem_request *request;
+	struct mock_request *mock;
+
+	/* NB the i915->requests slab cache is enlarged to fit mock_request */
+	request = i915_gem_request_alloc(engine, context);
+	if (!request)
+		return NULL;
+
+	mock = container_of(request, typeof(*mock), base);
+	INIT_LIST_HEAD(&mock->link);
+	mock->delay = delay;
+
+	return &mock->base;
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_request.h b/drivers/gpu/drm/i915/selftests/mock_request.h
new file mode 100644
index 000000000000..9c739125cab5
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_request.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __MOCK_REQUEST__
+#define __MOCK_REQUEST__
+
+#include <linux/list.h>
+
+#include "i915_gem_request.h"
+
+struct mock_request {
+	struct drm_i915_gem_request base;
+
+	struct list_head link;
+	unsigned long delay;
+};
+
+struct drm_i915_gem_request *
+mock_request(struct intel_engine_cs *engine,
+	     struct i915_gem_context *context,
+	     unsigned long delay);
+
+#endif /* !__MOCK_REQUEST__ */
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 10/19] drm/i915: Add selftests for i915_gem_request
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (7 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 09/19] drm/i915: Mock infrastructure for request emission Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 11/19] drm/i915: Add a simple request selftest for waiting Chris Wilson
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Simple starting point for adding seltests for i915_gem_request, first
mock a device (with engines and contexts) that allows us to construct
and execute a request, along with waiting for the request to complete.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_request.c            |  5 ++
 drivers/gpu/drm/i915/selftests/i915_gem_request.c  | 66 ++++++++++++++++++++++
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |  1 +
 3 files changed, 72 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_request.c

diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index 7427aac74923..1ac3a134ae1a 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -1208,3 +1208,8 @@ void i915_gem_retire_requests(struct drm_i915_private *dev_priv)
 	for_each_engine(engine, dev_priv, id)
 		engine_retire_requests(engine);
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/mock_request.c"
+#include "selftests/i915_gem_request.c"
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c
new file mode 100644
index 000000000000..43d92d8c8377
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_selftest.h"
+
+#include "mock_gem_device.h"
+
+static int igt_add_request(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_request *request;
+	int err = -ENOMEM;
+
+	mutex_lock(&i915->drm.struct_mutex);
+	request = mock_request(i915->engine[RCS],
+			       i915->kernel_context,
+			       HZ / 10);
+	if (!request)
+		goto out_unlock;
+
+	i915_add_request(request);
+
+	err = 0;
+out_unlock:
+	mutex_unlock(&i915->drm.struct_mutex);
+	return err;
+}
+
+int i915_gem_request_selftest(void)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_add_request),
+	};
+	struct drm_i915_private *i915;
+	int err;
+
+	i915 = mock_gem_device();
+	if (!i915)
+		return -ENOMEM;
+
+	err = i915_subtests(tests, i915);
+	drm_dev_unref(&i915->drm);
+
+	return err;
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index fdee6c88e415..09374df0d867 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -11,3 +11,4 @@
 selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */
 selftest(scatterlist, mock_scatterlist_selftests)
 selftest(breadcrumbs, intel_breadcrumbs_selftest)
+selftest(requests, i915_gem_request_selftest)
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 11/19] drm/i915: Add a simple request selftest for waiting
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (8 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 10/19] drm/i915: Add selftests for i915_gem_request Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 12/19] drm/i915: Add a simple fence selftest to i915_gem_request Chris Wilson
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

A trivial kselftest to submit a request and wait upon it.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/selftests/i915_gem_request.c | 44 +++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c
index 43d92d8c8377..743a641b1cd9 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c
@@ -47,10 +47,54 @@ static int igt_add_request(void *arg)
 	return err;
 }
 
+static int igt_wait_request(void *arg)
+{
+	const long T = HZ / 4;
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_request *request;
+	int err = -EINVAL;
+
+	mutex_lock(&i915->drm.struct_mutex);
+	request = mock_request(i915->engine[RCS], i915->kernel_context, T);
+	if (!request) {
+		err = -ENOMEM;
+		goto out_unlock;
+	}
+
+	i915_add_request(request);
+
+	if (i915_gem_request_completed(request)) {
+		pr_err("request completed immediately!\n");
+		goto out_unlock;
+	}
+
+	if (i915_wait_request(request, I915_WAIT_LOCKED, T / 2) != -ETIME) {
+		pr_err("request wait succeeded (expected tiemout!)\n");
+		goto out_unlock;
+	}
+
+	if (i915_wait_request(request, I915_WAIT_LOCKED, T) == -ETIME) {
+		pr_err("request wait timed out!\n");
+		goto out_unlock;
+	}
+
+	if (!i915_gem_request_completed(request)) {
+		pr_err("request not complete after waiting!\n");
+		goto out_unlock;
+	}
+
+	err = 0;
+out_unlock:
+	mock_device_flush(i915);
+	mutex_unlock(&i915->drm.struct_mutex);
+	return err;
+}
+
 int i915_gem_request_selftest(void)
 {
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_add_request),
+		SUBTEST(igt_wait_request),
 	};
 	struct drm_i915_private *i915;
 	int err;
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 12/19] drm/i915: Add a simple fence selftest to i915_gem_request
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (9 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 11/19] drm/i915: Add a simple request selftest for waiting Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 13/19] drm/i915: Add selftests for object allocation, phys Chris Wilson
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Do a quick selftest on in the interoperability of dma_fence_wait on a
i915_gem_request.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/selftests/i915_gem_request.c | 47 +++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c
index 743a641b1cd9..e91633ee721c 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c
@@ -90,11 +90,58 @@ static int igt_wait_request(void *arg)
 	return err;
 }
 
+static int igt_fence_wait(void *arg)
+{
+	const long T = HZ / 4;
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_request *request;
+	int err = -EINVAL;
+
+	mutex_lock(&i915->drm.struct_mutex);
+	request = mock_request(i915->engine[RCS], i915->kernel_context, T);
+	if (!request) {
+		err = -ENOMEM;
+		goto out_locked;
+	}
+
+	i915_add_request(request);
+	mutex_unlock(&i915->drm.struct_mutex);
+
+	if (dma_fence_is_signaled(&request->fence)) {
+		pr_err("fence signaled immediately!\n");
+		goto out_device;
+	}
+
+	if (dma_fence_wait_timeout(&request->fence, false, T / 2) != -ETIME) {
+		pr_err("fence wait success after submit (expected timeout)!\n");
+		goto out_device;
+	}
+
+	if (dma_fence_wait_timeout(&request->fence, false, T) <= 0) {
+		pr_err("fence wait timed out (expected success)!\n");
+		goto out_device;
+	}
+
+	if (!dma_fence_is_signaled(&request->fence)) {
+		pr_err("fence unsignaled after waiting!\n");
+		goto out_device;
+	}
+
+	err = 0;
+out_device:
+	mutex_lock(&i915->drm.struct_mutex);
+out_locked:
+	mock_device_flush(i915);
+	mutex_unlock(&i915->drm.struct_mutex);
+	return err;
+}
+
 int i915_gem_request_selftest(void)
 {
 	static const struct i915_subtest tests[] = {
 		SUBTEST(igt_add_request),
 		SUBTEST(igt_wait_request),
+		SUBTEST(igt_fence_wait),
 	};
 	struct drm_i915_private *i915;
 	int err;
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 13/19] drm/i915: Add selftests for object allocation, phys
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (10 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 12/19] drm/i915: Add a simple fence selftest to i915_gem_request Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2016-12-20 13:08 ` [RFCv2 14/19] drm/i915: Move uncore selfchecks to live selftest infrastructure Chris Wilson
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

The phys object is a rarely used device (only very old machines require
a chunk of physically contiguous pages for a few hardware interactions).
As such, it is not exercised by CI and to combat that we want to add a
test that exercises the phys object on all platforms.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c                    |   1 +
 drivers/gpu/drm/i915/selftests/i915_gem_object.c   | 114 +++++++++++++++++++++
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |   1 +
 3 files changed, 116 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_object.c

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index f52f1aafb4b9..81d24227ecca 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4977,4 +4977,5 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/scatterlist.c"
 #include "selftests/mock_gem_device.c"
+#include "selftests/i915_gem_object.c"
 #endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
new file mode 100644
index 000000000000..3ae3bbdd4e42
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_selftest.h"
+
+#include "mock_gem_device.h"
+
+static int igt_gem_object(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	int err = -ENOMEM;
+
+	obj = i915_gem_object_create(i915, PAGE_SIZE);
+	if (IS_ERR(obj)) {
+		err = PTR_ERR(obj);
+		pr_err("i915_gem_object_create failed, err=%d\n", err);
+		goto out;
+	}
+
+	err = 0;
+	i915_gem_object_put(obj);
+out:
+	return err;
+}
+
+static int igt_phys_object(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	int err = -ENOMEM;
+
+	obj = i915_gem_object_create(i915, PAGE_SIZE);
+	if (IS_ERR(obj)) {
+		err = PTR_ERR(obj);
+		pr_err("i915_gem_object_create failed, err=%d\n", err);
+		goto out;
+	}
+
+	err = -EINVAL;
+	mutex_lock(&i915->drm.struct_mutex);
+	err = i915_gem_object_attach_phys(obj, PAGE_SIZE);
+	mutex_unlock(&i915->drm.struct_mutex);
+	if (err) {
+		pr_err("i915_gem_object_attach_phys failed, err=%d\n", err);
+		goto err;
+	}
+
+	if (obj->ops != &i915_gem_phys_ops) {
+		pr_err("i915_gem_object_attach_phys did not create a phys object\n");
+		goto err;
+	}
+
+	if (!atomic_read(&obj->mm.pages_pin_count)) {
+		pr_err("i915_gem_object_attach_phys did not pin its phys pages\n");
+		goto err;
+	}
+
+	/* Make the object dirty so that put_pages must do copy back the data */
+	mutex_lock(&i915->drm.struct_mutex);
+	err = i915_gem_object_set_to_gtt_domain(obj, true);
+	mutex_unlock(&i915->drm.struct_mutex);
+	if (err) {
+		pr_err("i915_gem_object_set_to_gtt_domain failed with err=%d\n",
+		       err);
+		goto err;
+	}
+
+	err = 0;
+err:
+	i915_gem_object_put(obj);
+out:
+	return err;
+}
+
+int i915_gem_object_selftests(void)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_gem_object),
+		SUBTEST(igt_phys_object),
+	};
+	struct drm_i915_private *i915;
+	int err;
+
+	i915 = mock_gem_device();
+	if (!i915)
+		return -ENOMEM;
+
+	err = i915_subtests(tests, i915);
+
+	drm_dev_unref(&i915->drm);
+	return err;
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index 09374df0d867..33390b2530a7 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -12,3 +12,4 @@ selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */
 selftest(scatterlist, mock_scatterlist_selftests)
 selftest(breadcrumbs, intel_breadcrumbs_selftest)
 selftest(requests, i915_gem_request_selftest)
+selftest(objects, i915_gem_object_selftests)
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 14/19] drm/i915: Move uncore selfchecks to live selftest infrastructure
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (11 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 13/19] drm/i915: Add selftests for object allocation, phys Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-11 18:21   ` Matthew Auld
  2016-12-20 13:08 ` [RFCv2 15/19] drm/i915: Test all fw tables during mock selftests Chris Wilson
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Now that the kselftest infrastructure exists, put it to use and add to
it the existing consistency checks on the fw register lookup tables.

v2: s/tabke/table/

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/intel_uncore.c                | 52 +-----------
 .../gpu/drm/i915/selftests/i915_live_selftests.h   |  1 +
 drivers/gpu/drm/i915/selftests/intel_uncore.c      | 99 ++++++++++++++++++++++
 3 files changed, 104 insertions(+), 48 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/selftests/intel_uncore.c

diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 8fc5f29e79a8..3ab2d891f585 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -635,33 +635,6 @@ find_fw_domain(struct drm_i915_private *dev_priv, u32 offset)
 	return entry->domains;
 }
 
-static void
-intel_fw_table_check(struct drm_i915_private *dev_priv)
-{
-	const struct intel_forcewake_range *ranges;
-	unsigned int num_ranges;
-	s32 prev;
-	unsigned int i;
-
-	if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG))
-		return;
-
-	ranges = dev_priv->uncore.fw_domains_table;
-	if (!ranges)
-		return;
-
-	num_ranges = dev_priv->uncore.fw_domains_table_entries;
-
-	for (i = 0, prev = -1; i < num_ranges; i++, ranges++) {
-		WARN_ON_ONCE(IS_GEN9(dev_priv) &&
-			     (prev + 1) != (s32)ranges->start);
-		WARN_ON_ONCE(prev >= (s32)ranges->start);
-		prev = ranges->start;
-		WARN_ON_ONCE(prev >= (s32)ranges->end);
-		prev = ranges->end;
-	}
-}
-
 #define GEN_FW_RANGE(s, e, d) \
 	{ .start = (s), .end = (e), .domains = (d) }
 
@@ -700,23 +673,6 @@ static const i915_reg_t gen8_shadowed_regs[] = {
 	/* TODO: Other registers are not yet used */
 };
 
-static void intel_shadow_table_check(void)
-{
-	const i915_reg_t *reg = gen8_shadowed_regs;
-	s32 prev;
-	u32 offset;
-	unsigned int i;
-
-	if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG))
-		return;
-
-	for (i = 0, prev = -1; i < ARRAY_SIZE(gen8_shadowed_regs); i++, reg++) {
-		offset = i915_mmio_reg_offset(*reg);
-		WARN_ON_ONCE(prev >= (s32)offset);
-		prev = offset;
-	}
-}
-
 static int mmio_reg_cmp(u32 key, const i915_reg_t *reg)
 {
 	u32 offset = i915_mmio_reg_offset(*reg);
@@ -1445,10 +1401,6 @@ void intel_uncore_init(struct drm_i915_private *dev_priv)
 		break;
 	}
 
-	intel_fw_table_check(dev_priv);
-	if (INTEL_GEN(dev_priv) >= 8)
-		intel_shadow_table_check();
-
 	if (intel_vgpu_active(dev_priv)) {
 		ASSIGN_WRITE_MMIO_VFUNCS(vgpu);
 		ASSIGN_READ_MMIO_VFUNCS(vgpu);
@@ -1971,3 +1923,7 @@ intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv,
 
 	return fw_domains;
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/intel_uncore.c"
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index f3e17cb10e05..3d1d2719ec64 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -9,3 +9,4 @@
  * Tests are executed in order by igt/drv_selftest
  */
 selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */
+selftest(uncore, intel_uncore_live_selftests)
diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
new file mode 100644
index 000000000000..0ac467940a4f
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_selftest.h"
+
+static int intel_fw_table_check(struct drm_i915_private *i915)
+{
+	const struct intel_forcewake_range *ranges;
+	unsigned int num_ranges, i;
+	s32 prev;
+
+	ranges = i915->uncore.fw_domains_table;
+	if (!ranges)
+		return 0;
+
+	num_ranges = i915->uncore.fw_domains_table_entries;
+	for (i = 0, prev = -1; i < num_ranges; i++, ranges++) {
+		/* Check that the table is watertight */
+		if (IS_GEN9(i915) && (prev + 1) != (s32)ranges->start) {
+			pr_err("%s: entry[%d]:(%x, %x) is not watertight to previous (%x)\n",
+			       __func__, i, ranges->start, ranges->end, prev);
+			return -EINVAL;
+		}
+
+		/* Check that the table never goes backwards */
+		if (prev >= (s32)ranges->start) {
+			pr_err("%s: entry[%d]:(%x, %x) is less than the previous (%x)\n",
+			       __func__, i, ranges->start, ranges->end, prev);
+			return -EINVAL;
+		}
+
+		/* Check that the entry is valid */
+		if (ranges->start >= ranges->end) {
+			pr_err("%s: entry[%d]:(%x, %x) has negative length\n",
+			       __func__, i, ranges->start, ranges->end);
+			return -EINVAL;
+		}
+
+		prev = ranges->end;
+	}
+
+	return 0;
+}
+
+static int intel_shadow_table_check(void)
+{
+	const i915_reg_t *reg = gen8_shadowed_regs;
+	unsigned int i;
+	s32 prev;
+
+	for (i = 0, prev = -1; i < ARRAY_SIZE(gen8_shadowed_regs); i++, reg++) {
+		u32 offset = i915_mmio_reg_offset(*reg);
+		if (prev >= (s32)offset) {
+			pr_err("%s: entry[%d]:(%x) is before previous (%x)\n",
+			       __func__, i, offset, prev);
+			return -EINVAL;
+		}
+
+		prev = offset;
+	}
+
+	return 0;
+}
+
+int intel_uncore_live_selftests(struct drm_i915_private *i915)
+{
+	int err;
+
+	err = intel_fw_table_check(i915);
+	if (err)
+		return err;
+
+	err = intel_shadow_table_check();
+	if (err)
+		return err;
+
+	return 0;
+}
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 15/19] drm/i915: Test all fw tables during mock selftests
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (12 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 14/19] drm/i915: Move uncore selfchecks to live selftest infrastructure Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-11 18:22   ` Matthew Auld
  2016-12-20 13:08 ` [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains Chris Wilson
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

In addition to just testing the fw table we load, during the initial
mock testing we can test that all tables are valid (so the testing is
not limited to just the platforms that load that particular table).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |  1 +
 drivers/gpu/drm/i915/selftests/intel_uncore.c      | 49 ++++++++++++++++------
 2 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index 33390b2530a7..390af5cd895e 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -10,6 +10,7 @@
  */
 selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */
 selftest(scatterlist, mock_scatterlist_selftests)
+selftest(uncore, intel_uncore_mock_selftests)
 selftest(breadcrumbs, intel_breadcrumbs_selftest)
 selftest(requests, i915_gem_request_selftest)
 selftest(objects, i915_gem_object_selftests)
diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
index 0ac467940a4f..c18fddb12d00 100644
--- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
+++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
@@ -24,20 +24,16 @@
 
 #include "i915_selftest.h"
 
-static int intel_fw_table_check(struct drm_i915_private *i915)
+static int intel_fw_table_check(const struct intel_forcewake_range *ranges,
+				unsigned int num_ranges,
+				bool is_watertight)
 {
-	const struct intel_forcewake_range *ranges;
-	unsigned int num_ranges, i;
+	unsigned int i;
 	s32 prev;
 
-	ranges = i915->uncore.fw_domains_table;
-	if (!ranges)
-		return 0;
-
-	num_ranges = i915->uncore.fw_domains_table_entries;
 	for (i = 0, prev = -1; i < num_ranges; i++, ranges++) {
 		/* Check that the table is watertight */
-		if (IS_GEN9(i915) && (prev + 1) != (s32)ranges->start) {
+		if (is_watertight && (prev + 1) != (s32)ranges->start) {
 			pr_err("%s: entry[%d]:(%x, %x) is not watertight to previous (%x)\n",
 			       __func__, i, ranges->start, ranges->end, prev);
 			return -EINVAL;
@@ -83,15 +79,42 @@ static int intel_shadow_table_check(void)
 	return 0;
 }
 
-int intel_uncore_live_selftests(struct drm_i915_private *i915)
+int intel_uncore_mock_selftests(void)
 {
-	int err;
+	struct {
+		const struct intel_forcewake_range *ranges;
+		unsigned int num_ranges;
+		bool is_watertight;
+	} fw[] = {
+		{ __vlv_fw_ranges, ARRAY_SIZE(__vlv_fw_ranges), false },
+		{ __chv_fw_ranges, ARRAY_SIZE(__chv_fw_ranges), false },
+		{ __gen9_fw_ranges, ARRAY_SIZE(__gen9_fw_ranges), true },
+	};
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(fw); i++) {
+		err = intel_fw_table_check(fw[i].ranges,
+					   fw[i].num_ranges,
+					   fw[i].is_watertight);
+		if (err)
+			return err;
+	}
 
-	err = intel_fw_table_check(i915);
+	err = intel_shadow_table_check();
 	if (err)
 		return err;
 
-	err = intel_shadow_table_check();
+	return 0;
+}
+
+int intel_uncore_live_selftests(struct drm_i915_private *i915)
+{
+	int err;
+
+	/* Confirm the table we load is still valid */
+	err = intel_fw_table_check(i915->uncore.fw_domains_table,
+				   i915->uncore.fw_domains_table_entries,
+				   INTEL_GEN(i915) >= 9);
 	if (err)
 		return err;
 
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (13 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 15/19] drm/i915: Test all fw tables during mock selftests Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-11 18:25   ` Matthew Auld
  2017-01-11 19:08   ` Matthew Auld
  2016-12-20 13:08 ` [RFCv2 17/19] drm/i915: Add some mock tests for dmabuf interop Chris Wilson
                   ` (4 subsequent siblings)
  19 siblings, 2 replies; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Add a late selftest that walks over all forcewake registers (those below
0x40000) and checks intel_uncore_forcewake_for_reg() that the look
exists and we having the matching powerwells.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/selftests/intel_uncore.c | 47 +++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
index c18fddb12d00..c9f90514500f 100644
--- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
+++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
@@ -107,6 +107,49 @@ int intel_uncore_mock_selftests(void)
 	return 0;
 }
 
+static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_priv)
+{
+#define FW_RANGE 0x40000
+	unsigned long *valid;
+	u32 offset;
+	int err;
+
+	valid = kzalloc(BITS_TO_LONGS(FW_RANGE) * sizeof(*valid),
+			GFP_TEMPORARY);
+	if (!valid)
+		return -ENOMEM;
+
+	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+
+	check_for_unclaimed_mmio(dev_priv);
+	for (offset = 0; offset < FW_RANGE; offset += 4) {
+		i915_reg_t reg = { offset };
+
+		(void)I915_READ_FW(reg);
+		if (!check_for_unclaimed_mmio(dev_priv))
+			set_bit(offset, valid);
+	}
+
+	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
+	for_each_set_bit(offset, valid, FW_RANGE) {
+		i915_reg_t reg = { offset };
+
+		intel_uncore_forcewake_reset(dev_priv, false);
+		check_for_unclaimed_mmio(dev_priv);
+
+		(void)I915_READ(reg);
+		if (check_for_unclaimed_mmio(dev_priv)) {
+			pr_err("Unclaimed mmio read to register 0x%04x\n",
+			       offset);
+			err = -EINVAL;
+		}
+	}
+
+	kfree(valid);
+	return err;
+}
+
 int intel_uncore_live_selftests(struct drm_i915_private *i915)
 {
 	int err;
@@ -118,5 +161,9 @@ int intel_uncore_live_selftests(struct drm_i915_private *i915)
 	if (err)
 		return err;
 
+	err = intel_uncore_check_forcewake_domains(i915);
+	if (err)
+		return err;
+
 	return 0;
 }
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 17/19] drm/i915: Add some mock tests for dmabuf interop
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (14 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-10 19:12   ` Matthew Auld
  2016-12-20 13:08 ` [RFCv2 18/19] drm/i915: Add initial selftests for i915_gem_gtt Chris Wilson
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Check that we can create both dmabuf and objects from dmabuf.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_dmabuf.c             |   5 +
 drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c   | 297 +++++++++++++++++++++
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |   1 +
 drivers/gpu/drm/i915/selftests/mock_dmabuf.c       | 176 ++++++++++++
 drivers/gpu/drm/i915/selftests/mock_dmabuf.h       |  43 +++
 5 files changed, 522 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.c
 create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.h

diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index d037adcda6f2..3e276eee0450 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -307,3 +307,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 
 	return ERR_PTR(ret);
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/mock_dmabuf.c"
+#include "selftests/i915_gem_dmabuf.c"
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
new file mode 100644
index 000000000000..115c477978f7
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_selftest.h"
+
+#include "mock_gem_device.h"
+#include "mock_dmabuf.h"
+
+static int igt_dmabuf_export(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	struct dma_buf *dmabuf;
+	int err;
+
+	obj = i915_gem_object_create(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
+	if (IS_ERR(dmabuf)) {
+		pr_err("i915_gem_prime_export failed with err=%d\n",
+		       (int)PTR_ERR(dmabuf));
+		err = PTR_ERR(dmabuf);
+		goto err;
+	}
+
+	err = 0;
+	dma_buf_put(dmabuf);
+err:
+	i915_gem_object_put(obj);
+	return err;
+}
+
+static int igt_dmabuf_import_self(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	struct drm_gem_object *import;
+	struct dma_buf *dmabuf;
+	int err;
+
+	obj = i915_gem_object_create(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
+	if (IS_ERR(dmabuf)) {
+		pr_err("i915_gem_prime_export failed with err=%d\n",
+		       (int)PTR_ERR(dmabuf));
+		err = PTR_ERR(dmabuf);
+		goto err;
+	}
+
+	import = i915_gem_prime_import(&i915->drm, dmabuf);
+	if (IS_ERR(import)) {
+		pr_err("i915_gem_prime_import failed with err=%d\n",
+		       (int)PTR_ERR(import));
+		err = PTR_ERR(import);
+		goto err_dmabuf;
+	}
+
+	if (import != &obj->base) {
+		pr_err("i915_gem_prime_import created a new object!\n");
+		err = -EINVAL;
+		goto err_import;
+	}
+
+	err = 0;
+err_import:
+	i915_gem_object_put(to_intel_bo(import));
+err_dmabuf:
+	dma_buf_put(dmabuf);
+err:
+	i915_gem_object_put(obj);
+	return err;
+}
+
+static int igt_dmabuf_import(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	struct dma_buf *dmabuf;
+	void *obj_map, *dma_map;
+	u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff };
+	int err, i;
+
+	dmabuf = mock_dmabuf(1);
+	if (IS_ERR(dmabuf))
+		return PTR_ERR(dmabuf);
+
+	obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
+	if (IS_ERR(obj)) {
+		pr_err("i915_gem_prime_import failed with err=%d\n",
+		       (int)PTR_ERR(obj));
+		err = PTR_ERR(obj);
+		goto err_dmabuf;
+	}
+
+	if (obj->base.dev != &i915->drm) {
+		pr_err("i915_gem_prime_import created a non-i915 object!\n");
+		err = -EINVAL;
+		goto err_obj;
+	}
+
+	if (obj->base.size != PAGE_SIZE) {
+		pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n",
+		       (long long)obj->base.size, PAGE_SIZE);
+		err = -EINVAL;
+		goto err_obj;
+	}
+
+	dma_map = dma_buf_vmap(dmabuf);
+	if (!dma_map) {
+		pr_err("dma_buf_vmap failed\n");
+		err = -ENOMEM;
+		goto err_obj;
+	}
+
+	if (0) {
+		/* Can not yet map dmabuf */
+		obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB);
+		if (IS_ERR(obj_map)) {
+			err = PTR_ERR(obj_map);
+			pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
+			goto err_dma_map;
+		}
+
+		for (i = 0; i < ARRAY_SIZE(pattern); i++) {
+			memset(dma_map, pattern[i], PAGE_SIZE);
+			if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) {
+				err = -EINVAL;
+				pr_err("imported vmap not all set to %x!\n", pattern[i]);
+				i915_gem_object_unpin_map(obj);
+				goto err_dma_map;
+			}
+		}
+
+		for (i = 0; i < ARRAY_SIZE(pattern); i++) {
+			memset(obj_map, pattern[i], PAGE_SIZE);
+			if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) {
+				err = -EINVAL;
+				pr_err("exported vmap not all set to %x!\n", pattern[i]);
+				i915_gem_object_unpin_map(obj);
+				goto err_dma_map;
+			}
+		}
+	}
+
+	err = 0;
+err_dma_map:
+	dma_buf_vunmap(dmabuf, dma_map);
+err_obj:
+	i915_gem_object_put(obj);
+err_dmabuf:
+	dma_buf_put(dmabuf);
+	return err;
+}
+
+static int igt_dmabuf_import_ownership(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	struct dma_buf *dmabuf;
+	void *ptr;
+	int err;
+
+	dmabuf = mock_dmabuf(1);
+	if (IS_ERR(dmabuf))
+		return PTR_ERR(dmabuf);
+
+	ptr = dma_buf_vmap(dmabuf);
+	if (!ptr) {
+		pr_err("dma_buf_vmap failed\n");
+		err = -ENOMEM;
+		goto err_dmabuf;
+	}
+
+	memset(ptr, 0xc5, PAGE_SIZE);
+	dma_buf_vunmap(dmabuf, ptr);
+
+	obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
+	if (IS_ERR(obj)) {
+		pr_err("i915_gem_prime_import failed with err=%d\n",
+		       (int)PTR_ERR(obj));
+		err = PTR_ERR(obj);
+		goto err_dmabuf;
+	}
+
+	dma_buf_put(dmabuf);
+
+	err = i915_gem_object_pin_pages(obj);
+	if (err) {
+		pr_err("i915_gem_object_pin_pages failed with err=%d\n", err);
+		goto err_obj;
+	}
+
+	err = 0;
+	i915_gem_object_unpin_pages(obj);
+err_obj:
+	i915_gem_object_put(obj);
+	return err;
+
+err_dmabuf:
+	dma_buf_put(dmabuf);
+	return err;
+}
+
+static int igt_dmabuf_export_vmap(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	struct dma_buf *dmabuf;
+	void *ptr;
+	int err;
+
+	obj = i915_gem_object_create(i915, PAGE_SIZE);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
+	if (IS_ERR(dmabuf)) {
+		pr_err("i915_gem_prime_export failed with err=%d\n",
+		       (int)PTR_ERR(dmabuf));
+		err = PTR_ERR(dmabuf);
+		goto err_obj;
+	}
+	i915_gem_object_put(obj);
+
+	ptr = dma_buf_vmap(dmabuf);
+	if (IS_ERR(ptr)) {
+		err = PTR_ERR(ptr);
+		pr_err("dma_buf_vmap failed with err=%d\n", err);
+		goto err;
+	}
+
+	if(memchr_inv(ptr, 0, dmabuf->size)) {
+		pr_err("Exported object no initialiased to zero!\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	memset(ptr, 0xc5, dmabuf->size);
+
+	err = 0;
+	dma_buf_vunmap(dmabuf, ptr);
+err:
+	dma_buf_put(dmabuf);
+	return err;
+
+err_obj:
+	i915_gem_object_put(obj);
+	return err;
+}
+
+int i915_gem_dmabuf_selftest(void)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_dmabuf_export),
+		SUBTEST(igt_dmabuf_import_self),
+		SUBTEST(igt_dmabuf_import),
+		SUBTEST(igt_dmabuf_import_ownership),
+		SUBTEST(igt_dmabuf_export_vmap),
+	};
+	struct drm_i915_private *i915;
+	int err;
+
+	i915 = mock_gem_device();
+	if (!i915)
+		return -ENOMEM;
+
+	err = i915_subtests(tests, i915);
+
+	drm_dev_unref(&i915->drm);
+	return err;
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index 390af5cd895e..417bcfa3cdba 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -14,3 +14,4 @@ selftest(uncore, intel_uncore_mock_selftests)
 selftest(breadcrumbs, intel_breadcrumbs_selftest)
 selftest(requests, i915_gem_request_selftest)
 selftest(objects, i915_gem_object_selftests)
+selftest(dmabuf, i915_gem_dmabuf_selftest)
diff --git a/drivers/gpu/drm/i915/selftests/mock_dmabuf.c b/drivers/gpu/drm/i915/selftests/mock_dmabuf.c
new file mode 100644
index 000000000000..515691779540
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_dmabuf.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "mock_dmabuf.h"
+
+static struct sg_table *mock_map_dma_buf(struct dma_buf_attachment *attachment,
+					 enum dma_data_direction dir)
+{
+	struct mock_dmabuf *mock = to_mock(attachment->dmabuf);
+	struct sg_table *st;
+	struct scatterlist *sg;
+	int i, err;
+
+	st = kmalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return ERR_PTR(-ENOMEM);
+
+	err = sg_alloc_table(st, mock->npages, GFP_KERNEL);
+	if (err)
+		goto err_free;
+
+	sg = st->sgl;
+	for (i = 0; i < mock->npages; i++) {
+		sg_set_page(sg, mock->pages[i], PAGE_SIZE, 0);
+		sg = sg_next(sg);
+	}
+
+	if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
+		err = -ENOMEM;
+		goto err_st;
+	}
+
+	return st;
+
+err_st:
+	sg_free_table(st);
+err_free:
+	kfree(st);
+	return ERR_PTR(err);
+}
+
+static void mock_unmap_dma_buf(struct dma_buf_attachment *attachment,
+			       struct sg_table *st,
+			       enum dma_data_direction dir)
+{
+	dma_unmap_sg(attachment->dev, st->sgl, st->nents, dir);
+	sg_free_table(st);
+	kfree(st);
+}
+
+static void mock_dmabuf_release(struct dma_buf *dma_buf)
+{
+	struct mock_dmabuf *mock = to_mock(dma_buf);
+	int i;
+
+	for (i = 0; i < mock->npages; i++)
+		put_page(mock->pages[i]);
+
+	kfree(mock);
+}
+
+static void *mock_dmabuf_vmap(struct dma_buf *dma_buf)
+{
+	struct mock_dmabuf *mock = to_mock(dma_buf);
+
+	return vm_map_ram(mock->pages, mock->npages, 0, PAGE_KERNEL);
+}
+
+static void mock_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
+{
+	struct mock_dmabuf *mock = to_mock(dma_buf);
+
+	vm_unmap_ram(vaddr, mock->npages);
+}
+
+static void *mock_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
+{
+	struct mock_dmabuf *mock = to_mock(dma_buf);
+
+	return kmap_atomic(mock->pages[page_num]);
+}
+
+static void mock_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
+{
+	kunmap_atomic(addr);
+}
+
+static void *mock_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
+{
+	struct mock_dmabuf *mock = to_mock(dma_buf);
+
+	return kmap(mock->pages[page_num]);
+}
+
+static void mock_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
+{
+	struct mock_dmabuf *mock = to_mock(dma_buf);
+
+	return kunmap(mock->pages[page_num]);
+}
+
+static int mock_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
+{
+	return -ENODEV;
+}
+
+static const struct dma_buf_ops mock_dmabuf_ops =  {
+	.map_dma_buf = mock_map_dma_buf,
+	.unmap_dma_buf = mock_unmap_dma_buf,
+	.release = mock_dmabuf_release,
+	.kmap = mock_dmabuf_kmap,
+	.kmap_atomic = mock_dmabuf_kmap_atomic,
+	.kunmap = mock_dmabuf_kunmap,
+	.kunmap_atomic = mock_dmabuf_kunmap_atomic,
+	.mmap = mock_dmabuf_mmap,
+	.vmap = mock_dmabuf_vmap,
+	.vunmap = mock_dmabuf_vunmap,
+};
+
+static struct dma_buf *mock_dmabuf(int npages)
+{
+	struct mock_dmabuf *mock;
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+	struct dma_buf *dmabuf;
+	int i;
+
+	mock = kmalloc(sizeof(*mock) + npages * sizeof(struct page *),
+		       GFP_KERNEL);
+	if (!mock)
+		return ERR_PTR(-ENOMEM);
+
+	mock->npages = npages;
+	for (i = 0; i < npages; i++) {
+		mock->pages[i] = alloc_page(GFP_KERNEL);
+		if (!mock->pages[i])
+			goto err;
+	}
+
+	exp_info.ops = &mock_dmabuf_ops;
+	exp_info.size = npages * PAGE_SIZE;
+	exp_info.flags = O_CLOEXEC;
+	exp_info.priv = mock;
+
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf))
+		goto err;
+
+	return dmabuf;
+
+err:
+	while (i--)
+		put_page(mock->pages[i]);
+	kfree(mock);
+	return NULL;
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_dmabuf.h b/drivers/gpu/drm/i915/selftests/mock_dmabuf.h
new file mode 100644
index 000000000000..bb5aaebcc80e
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/mock_dmabuf.h
@@ -0,0 +1,43 @@
+
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __MOCK_DMABUF_H__
+#define __MOCK_DMABUF_H__
+
+#include "mock_dmabuf.h"
+
+struct dma_buf;
+
+struct mock_dmabuf {
+	int npages;
+	struct page *pages[];
+};
+
+static struct mock_dmabuf *to_mock(struct dma_buf *buf)
+{
+	return buf->priv;
+}
+
+#endif /* !__MOCK_DMABUF_H__ */
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 18/19] drm/i915: Add initial selftests for i915_gem_gtt
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (15 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 17/19] drm/i915: Add some mock tests for dmabuf interop Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-10 19:32   ` Matthew Auld
  2016-12-20 13:08 ` [RFCv2 19/19] drm/i915: Initial selftests for exercising eviction Chris Wilson
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Simple starting point for adding seltests for i915_gem_gtt, first
try creating a ppGTT and filling it.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c                |  1 +
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c      | 95 ++++++++++++++++++++++
 .../gpu/drm/i915/selftests/i915_live_selftests.h   |  1 +
 3 files changed, 97 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 5a98e2ca5a53..4baa0aee62a5 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3579,4 +3579,5 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
 
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/mock_ggtt.c"
+#include "selftests/i915_gem_gtt.c"
 #endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
new file mode 100644
index 000000000000..97b55e9726d8
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_selftest.h"
+
+static int igt_ppgtt_alloc(void *arg)
+{
+	struct drm_i915_private *dev_priv = arg;
+	struct i915_hw_ppgtt *ppgtt;
+	u64 size, last;
+	int err;
+
+	if (!USES_PPGTT(dev_priv))
+		return 0;
+
+	ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
+	if (!ppgtt)
+		return -ENOMEM;
+
+	err = __hw_ppgtt_init(ppgtt, dev_priv);
+	if (err)
+		goto err_ppgtt;
+
+	if (!ppgtt->base.allocate_va_range)
+		goto err_ppgtt_cleanup;
+
+	/* Check we can allocate the entire range */
+	for (size = 4096;
+	     size <= ppgtt->base.total;
+	     size <<= 2) {
+		err = ppgtt->base.allocate_va_range(&ppgtt->base, 0, size);
+		if (err) {
+			if (err == -ENOMEM) {
+				pr_info("[1] Ran out of memory for va_range [0 + %llx] [bit %d]\n",
+					size, ilog2(size));
+				err = 0; /* virtual space too large! */
+			}
+			goto err_ppgtt_cleanup;
+		}
+
+		ppgtt->base.clear_range(&ppgtt->base, 0, size);
+	}
+
+	/* Check we can incrementally allocate the entire range */
+	for (last = 0, size = 4096;
+	     size <= ppgtt->base.total;
+	     last = size, size <<= 2) {
+		err = ppgtt->base.allocate_va_range(&ppgtt->base,
+						    last, size - last);
+		if (err) {
+			if (err == -ENOMEM) {
+				pr_info("[2] Ran out of memory for va_range [%llx + %llx] [bit %d]\n",
+					last, size - last, ilog2(size));
+				err = 0; /* virtual space too large! */
+			}
+			goto err_ppgtt_cleanup;
+		}
+	}
+
+err_ppgtt_cleanup:
+	ppgtt->base.cleanup(&ppgtt->base);
+err_ppgtt:
+	kfree(ppgtt);
+	return err;
+}
+
+int i915_gem_gtt_live_selftests(struct drm_i915_private *i915)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_ppgtt_alloc),
+	};
+
+	return i915_subtests(tests, i915);
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index 3d1d2719ec64..0c3765f42cef 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -10,3 +10,4 @@
  */
 selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */
 selftest(uncore, intel_uncore_live_selftests)
+selftest(gtt, i915_gem_gtt_live_selftests)
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFCv2 19/19] drm/i915: Initial selftests for exercising eviction
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (16 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 18/19] drm/i915: Add initial selftests for i915_gem_gtt Chris Wilson
@ 2016-12-20 13:08 ` Chris Wilson
  2017-01-10 19:49   ` Matthew Auld
  2016-12-20 14:16 ` ✓ Fi.CI.BAT: success for series starting with [RFCv2,01/19] drm/i915: Provide a hook for selftests Patchwork
  2017-01-11 18:17 ` [RFCv2 01/19] " Tvrtko Ursulin
  19 siblings, 1 reply; 33+ messages in thread
From: Chris Wilson @ 2016-12-20 13:08 UTC (permalink / raw)
  To: intel-gfx

Very simple tests to just ask eviction to find some free space in a full
GTT and one with some available space.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_evict.c              |   4 +
 drivers/gpu/drm/i915/selftests/i915_gem_evict.c    | 237 +++++++++++++++++++++
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |   1 +
 3 files changed, 242 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_evict.c

diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index f92f63e8749a..c01a9dd6298c 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -383,3 +383,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
 
 	return 0;
 }
+
+#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
+#include "selftests/i915_gem_evict.c"
+#endif
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
new file mode 100644
index 000000000000..c31e6a6c98cd
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_selftest.h"
+
+#include "mock_gem_device.h"
+
+static int populate_ggtt(struct drm_i915_private *i915)
+{
+	struct drm_i915_gem_object *obj;
+	u64 size;
+
+	for (size = 0; size < i915->ggtt.base.total; size += PAGE_SIZE) {
+		struct i915_vma *vma;
+
+		obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
+		if (IS_ERR(obj))
+			return PTR_ERR(obj);
+
+		vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
+		if (IS_ERR(vma))
+			return PTR_ERR(vma);
+	}
+
+	if (!list_empty(&i915->mm.unbound_list)) {
+		size = 0;
+		list_for_each_entry(obj, &i915->mm.unbound_list, global_link)
+			size++;
+
+		pr_err("Found %lld objects unbound!\n", size);
+		return -EINVAL;
+	}
+
+	if (list_empty(&i915->ggtt.base.inactive_list)) {
+		pr_err("No objects on the GGTT inactive list!\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void unpin_ggtt(struct drm_i915_private *i915)
+{
+	struct i915_vma *vma;
+
+	list_for_each_entry(vma, &i915->ggtt.base.inactive_list, vm_link)
+		i915_vma_unpin(vma);
+}
+
+static void cleanup_objects(struct drm_i915_private *i915)
+{
+	struct drm_i915_gem_object *obj, *on;
+
+	list_for_each_entry_safe(obj, on, &i915->mm.unbound_list, global_link)
+		i915_gem_object_put(obj);
+
+	list_for_each_entry_safe(obj, on, &i915->mm.bound_list, global_link)
+		i915_gem_object_put(obj);
+
+	mutex_unlock(&i915->drm.struct_mutex);
+
+	rcu_barrier();
+	while (flush_work(&i915->mm.free_work))
+		rcu_barrier();
+
+	mutex_lock(&i915->drm.struct_mutex);
+}
+
+static int igt_evict_something(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct i915_ggtt *ggtt = &i915->ggtt;
+	int err;
+
+	err = populate_ggtt(i915);
+	if (err)
+		goto cleanup;
+
+	err = i915_gem_evict_something(&ggtt->base,
+				       PAGE_SIZE, 0, 0,
+				       0, U64_MAX,
+				       0);
+	if (err != -ENOSPC) {
+		pr_err("i915_gem_evict_something failed on a full GGTT with err=%d\n",
+		       err);
+		goto cleanup;
+	}
+
+	unpin_ggtt(i915);
+
+	err = i915_gem_evict_something(&ggtt->base,
+				       PAGE_SIZE, 0, 0,
+				       0, U64_MAX,
+				       0);
+	if (err) {
+		pr_err("i915_gem_evict_something failed on a full GGTT with err=%d\n",
+		       err);
+		goto cleanup;
+	}
+
+cleanup:
+	cleanup_objects(i915);
+	return err;
+}
+
+static int igt_overcommit(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct drm_i915_gem_object *obj;
+	struct i915_vma *vma;
+	int err;
+
+	err = populate_ggtt(i915);
+	if (err)
+		goto cleanup;
+
+	obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
+	if (IS_ERR(obj)) {
+		err = PTR_ERR(obj);
+		goto cleanup;
+	}
+
+	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
+	if (IS_ERR(vma) && PTR_ERR(vma) != -ENOSPC) {
+		pr_err("Failed to evict+insert, i915_gem_object_ggtt_pin returned err=%d\n", (int)PTR_ERR(vma));
+		err = PTR_ERR(vma);
+		goto cleanup;
+	}
+
+cleanup:
+	cleanup_objects(i915);
+	return err;
+}
+
+static int igt_evict_for_vma(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct i915_ggtt *ggtt = &i915->ggtt;
+	struct i915_vma target = {
+		.node = {
+			.start = 0,
+			.size = 4096,
+		},
+		.vm = &ggtt->base,
+	};
+	int err;
+
+	err = populate_ggtt(i915);
+	if (err)
+		goto cleanup;
+
+	err = i915_gem_evict_for_vma(&target, 0);
+	if (err != -ENOSPC) {
+		pr_err("i915_gem_evict_for_vma on a full GGTT returned err=%d\n",
+		       err);
+		goto cleanup;
+	}
+
+	unpin_ggtt(i915);
+
+	err = i915_gem_evict_for_vma(&target, 0);
+	if (err) {
+		pr_err("i915_gem_evict_for_vma returned err=%d\n",
+		       err);
+		goto cleanup;
+	}
+
+cleanup:
+	cleanup_objects(i915);
+	return err;
+}
+
+static int igt_evict_vm(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct i915_ggtt *ggtt = &i915->ggtt;
+	int err;
+
+	err = populate_ggtt(i915);
+	if (err)
+		goto cleanup;
+
+	err = i915_gem_evict_vm(&ggtt->base, false);
+	if (err) {
+		pr_err("i915_gem_evict_vm on a full GGTT returned err=%d]\n",
+		       err);
+		goto cleanup;
+	}
+
+cleanup:
+	cleanup_objects(i915);
+	return err;
+}
+
+int i915_gem_evict_selftest(void)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(igt_evict_something),
+		SUBTEST(igt_evict_for_vma),
+		SUBTEST(igt_evict_vm),
+		SUBTEST(igt_overcommit),
+	};
+	struct drm_i915_private *i915;
+	int err;
+
+	i915 = mock_gem_device();
+	if (!i915)
+		return -ENOMEM;
+
+	mutex_lock(&i915->drm.struct_mutex);
+	err = i915_subtests(tests, i915);
+	mutex_unlock(&i915->drm.struct_mutex);
+
+	drm_dev_unref(&i915->drm);
+	return err;
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
index 417bcfa3cdba..f71f42a70a86 100644
--- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
@@ -15,3 +15,4 @@ selftest(breadcrumbs, intel_breadcrumbs_selftest)
 selftest(requests, i915_gem_request_selftest)
 selftest(objects, i915_gem_object_selftests)
 selftest(dmabuf, i915_gem_dmabuf_selftest)
+selftest(evict, i915_gem_evict_selftest)
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* ✓ Fi.CI.BAT: success for series starting with [RFCv2,01/19] drm/i915: Provide a hook for selftests
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (17 preceding siblings ...)
  2016-12-20 13:08 ` [RFCv2 19/19] drm/i915: Initial selftests for exercising eviction Chris Wilson
@ 2016-12-20 14:16 ` Patchwork
  2017-01-11 18:17 ` [RFCv2 01/19] " Tvrtko Ursulin
  19 siblings, 0 replies; 33+ messages in thread
From: Patchwork @ 2016-12-20 14:16 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [RFCv2,01/19] drm/i915: Provide a hook for selftests
URL   : https://patchwork.freedesktop.org/series/17057/
State : success

== Summary ==

Series 17057v1 Series without cover letter
https://patchwork.freedesktop.org/api/1.0/series/17057/revisions/1/mbox/

Test gem_sync:
        Subgroup basic-store-all:
                fail       -> PASS       (fi-ivb-3520m)

fi-bdw-5557u     total:247  pass:233  dwarn:0   dfail:0   fail:0   skip:14 
fi-bsw-n3050     total:247  pass:208  dwarn:0   dfail:0   fail:0   skip:39 
fi-bxt-j4205     total:247  pass:225  dwarn:1   dfail:0   fail:0   skip:21 
fi-byt-j1900     total:247  pass:220  dwarn:0   dfail:0   fail:0   skip:27 
fi-byt-n2820     total:247  pass:216  dwarn:0   dfail:0   fail:0   skip:31 
fi-hsw-4770      total:247  pass:228  dwarn:0   dfail:0   fail:0   skip:19 
fi-hsw-4770r     total:247  pass:228  dwarn:0   dfail:0   fail:0   skip:19 
fi-ilk-650       total:247  pass:195  dwarn:0   dfail:0   fail:0   skip:52 
fi-ivb-3520m     total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-ivb-3770      total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-kbl-7500u     total:247  pass:226  dwarn:0   dfail:0   fail:0   skip:21 
fi-skl-6260u     total:247  pass:234  dwarn:0   dfail:0   fail:0   skip:13 
fi-skl-6700hq    total:247  pass:227  dwarn:0   dfail:0   fail:0   skip:20 
fi-skl-6700k     total:247  pass:224  dwarn:3   dfail:0   fail:0   skip:20 
fi-skl-6770hq    total:247  pass:234  dwarn:0   dfail:0   fail:0   skip:13 
fi-snb-2520m     total:247  pass:216  dwarn:0   dfail:0   fail:0   skip:31 
fi-snb-2600      total:247  pass:215  dwarn:0   dfail:0   fail:0   skip:32 

b8e68c1d31266b62356d578435246516c39de36b drm-tip: 2016y-12m-20d-12h-47m-27s UTC integration manifest
c4bb35d kselftests: Exercise hw-independent mock tests for i915.ko
0e5ff42 drm/i915: Provide a hook for selftests

== Logs ==

For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_3340/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 07/19] drm/i915: Mock the GEM device for self-testing
  2016-12-20 13:08 ` [RFCv2 07/19] drm/i915: Mock the GEM device for self-testing Chris Wilson
@ 2017-01-09 15:10   ` Matthew Auld
  0 siblings, 0 replies; 33+ messages in thread
From: Matthew Auld @ 2017-01-09 15:10 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_gem.c                  |   1 +
>  drivers/gpu/drm/i915/selftests/mock_gem_device.c | 109 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/selftests/mock_gem_device.h |   8 ++
>  drivers/gpu/drm/i915/selftests/mock_gem_object.h |   8 ++
>  4 files changed, 126 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_device.c
>  create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_device.h
>  create mode 100644 drivers/gpu/drm/i915/selftests/mock_gem_object.h
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 4547d4cd2064..f52f1aafb4b9 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -4976,4 +4976,5 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
>
>  #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>  #include "selftests/scatterlist.c"
> +#include "selftests/mock_gem_device.c"
>  #endif
> diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> new file mode 100644
> index 000000000000..95cf1d845bf1
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> @@ -0,0 +1,109 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include <linux/pm_runtime.h>
> +
> +#include "mock_gem_device.h"
> +#include "mock_gem_object.h"
> +
> +static void mock_device_release(struct drm_device *dev)
> +{
> +       struct drm_i915_private *i915 = to_i915(dev);
> +
> +       rcu_barrier();
> +       while (flush_work(&i915->mm.free_work))
> +               rcu_barrier();
> +
> +       kmem_cache_destroy(i915->objects);
> +       put_device(&i915->drm.pdev->dev);
> +}
> +
> +static struct drm_driver mock_driver = {
> +       .name = "mock",
> +       .driver_features = DRIVER_GEM,
> +       .release = mock_device_release,
> +
> +       .gem_close_object = i915_gem_close_object,
> +       .gem_free_object_unlocked = i915_gem_free_object,
> +};
> +
> +static void release_dev(struct device *dev)
> +{
> +       struct pci_dev *pdev = to_pci_dev(dev);
> +
> +       kfree(pdev);
> +}
> +
> +struct drm_i915_private *mock_gem_device(void)
> +{
> +       struct drm_i915_private *i915;
> +       struct pci_dev *pdev;
> +       int err;
> +
> +       i915 = kzalloc(sizeof(*i915), GFP_TEMPORARY);
> +       if (!i915)
> +               return NULL;
> +
> +       pdev = kzalloc(sizeof(*pdev), GFP_TEMPORARY);
> +       if (!pdev) {
> +               kfree(i915);
> +               return NULL;
goto err_device;

> +       }
> +
> +       device_initialize(&pdev->dev);
> +       pdev->dev.release = release_dev;
> +       dev_set_name(&pdev->dev, "mock");
> +       dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +
> +       pm_runtime_dont_use_autosuspend(&pdev->dev);
> +       pm_runtime_get_sync(&pdev->dev);
> +       pci_set_drvdata(pdev, i915);
> +
> +       err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev);
> +       if (err) {
> +               pr_err("Failed to initialise mock GEM device: err=%d\n", err);
> +               put_device(&pdev->dev);
> +               kfree(i915);
> +               return NULL;
goto err_device;

> +       }
> +       i915->drm.pdev = pdev;
> +       i915->drm.dev_private = i915;
> +
> +       mkwrite_device_info(i915)->gen = -1;
> +
> +       spin_lock_init(&i915->mm.object_stat_lock);
> +
> +       INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
> +       init_llist_head(&i915->mm.free_list);
> +
> +       i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN);
> +       if (!i915->objects)
put_device(&pdev->dev);

With a proper commit message:
Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> +               goto err_device;
> +
> +       return i915;
> +
> +err_device:
> +       kfree(i915);
> +       return NULL;
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.h b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
> new file mode 100644
> index 000000000000..7ff7c848f731
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
> @@ -0,0 +1,8 @@
> +#ifndef __MOCK_GEM_DEVICE_H__
> +#define __MOCK_GEM_DEVICE_H__
> +
> +#include "i915_drv.h"
> +
> +struct drm_i915_private *mock_gem_device(void);
> +
> +#endif /* !__MOCK_GEM_DEVICE_H__ */
> diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_object.h b/drivers/gpu/drm/i915/selftests/mock_gem_object.h
> new file mode 100644
> index 000000000000..9fbf67321662
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/mock_gem_object.h
> @@ -0,0 +1,8 @@
> +#ifndef __MOCK_GEM_OBJECT_H__
> +#define __MOCK_GEM_OBJECT_H__
> +
> +struct mock_object {
> +       struct drm_i915_gem_object base;
> +};
> +
> +#endif /* !__MOCK_GEM_OBJECT_H__ */
> --
> 2.11.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 08/19] drm/i915: Mock a GGTT for self-testing
  2016-12-20 13:08 ` [RFCv2 08/19] drm/i915: Mock a GGTT " Chris Wilson
@ 2017-01-09 15:16   ` Matthew Auld
  2017-01-10 12:33     ` Chris Wilson
  0 siblings, 1 reply; 33+ messages in thread
From: Matthew Auld @ 2017-01-09 15:16 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> A very simple mockery, just a random manager and timeline. Useful for
> inserting objects and ordering retirement; and not much else.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_gem_gtt.c              |  4 ++
>  drivers/gpu/drm/i915/selftests/mock_gem_device.c | 22 +++++++
>  drivers/gpu/drm/i915/selftests/mock_gem_device.h |  1 +
>  drivers/gpu/drm/i915/selftests/mock_ggtt.c       | 79 ++++++++++++++++++++++++
>  4 files changed, 106 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/selftests/mock_ggtt.c
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index d35c46b477a6..5a98e2ca5a53 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -3576,3 +3576,7 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
>                                            size, alignment, colour,
>                                            start, end, DRM_MM_INSERT_EVICT);
>  }
> +
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +#include "selftests/mock_ggtt.c"
> +#endif
> diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> index 95cf1d845bf1..025012ba92eb 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> @@ -35,6 +35,7 @@ static void mock_device_release(struct drm_device *dev)
>         while (flush_work(&i915->mm.free_work))
>                 rcu_barrier();
>
> +       kmem_cache_destroy(i915->vmas);
i915_gem_timeline_fini also.

>         kmem_cache_destroy(i915->objects);
>         put_device(&i915->drm.pdev->dev);
>  }
> @@ -90,19 +91,40 @@ struct drm_i915_private *mock_gem_device(void)
>         i915->drm.pdev = pdev;
>         i915->drm.dev_private = i915;
>
> +       drm_mode_config_init(&i915->drm);
> +
Why do we need this for mocking the ggtt ?

>         mkwrite_device_info(i915)->gen = -1;
>
>         spin_lock_init(&i915->mm.object_stat_lock);
>
>         INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
>         init_llist_head(&i915->mm.free_list);
> +       INIT_LIST_HEAD(&i915->mm.unbound_list);
> +       INIT_LIST_HEAD(&i915->mm.bound_list);
>
>         i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN);
>         if (!i915->objects)
>                 goto err_device;
>
> +       i915->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
> +       if (!i915->vmas)
> +               goto err_objects;
> +
> +       mutex_lock(&i915->drm.struct_mutex);
> +       INIT_LIST_HEAD(&i915->gt.timelines);
> +       err = i915_gem_timeline_init__global(i915);
> +       if (err)
mutex_unlock(&i915->drm.struct_mutex);

> +               goto err_vmas;
> +
> +       mock_init_ggtt(i915);
> +       mutex_unlock(&i915->drm.struct_mutex);
> +
>         return i915;
>
> +err_vmas:
> +       kmem_cache_destroy(i915->vmas);
> +err_objects:
> +       kmem_cache_destroy(i915->objects);
>  err_device:
>         kfree(i915);
>         return NULL;
> diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.h b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
> index 7ff7c848f731..5189f684a17e 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.h
> +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.h
> @@ -4,5 +4,6 @@
>  #include "i915_drv.h"
>
>  struct drm_i915_private *mock_gem_device(void);
> +void mock_init_ggtt(struct drm_i915_private *i915);
>
>  #endif /* !__MOCK_GEM_DEVICE_H__ */
> diff --git a/drivers/gpu/drm/i915/selftests/mock_ggtt.c b/drivers/gpu/drm/i915/selftests/mock_ggtt.c
> new file mode 100644
> index 000000000000..d5f2811bc220
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/mock_ggtt.c
> @@ -0,0 +1,79 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "mock_gem_device.h"
> +
> +static void mock_insert_page(struct i915_address_space *vm,
> +                            dma_addr_t addr,
> +                            uint64_t offset,
> +                            enum i915_cache_level level,
> +                            u32 flags)
> +{
> +}
> +
> +static void mock_insert_entries(struct i915_address_space *vm,
> +                               struct sg_table *st,
> +                               uint64_t start,
> +                               enum i915_cache_level level, u32 flags)
> +{
> +}
> +
> +static int mock_bind_vma(struct i915_vma *vma,
> +                        enum i915_cache_level cache_level,
> +                        u32 flags)
> +{
> +       vma->pages = vma->obj->mm.pages;
> +       vma->flags |= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
> +       return 0;
> +}
> +
> +static void mock_unbind_vma(struct i915_vma *vma)
> +{
> +}
> +
> +static void mock_remove(struct i915_address_space *vm)
> +{
> +}
> +
> +void mock_init_ggtt(struct drm_i915_private *i915)
> +{
> +       struct i915_ggtt *ggtt = &i915->ggtt;
> +
> +       INIT_LIST_HEAD(&i915->vm_list);
> +
> +       ggtt->base.i915 = i915;
> +
> +       ggtt->mappable_base = 0;
> +       ggtt->mappable_end = 2048 * PAGE_SIZE;
> +       ggtt->base.total = 4096 * PAGE_SIZE;
> +
> +       ggtt->base.clear_range = nop_clear_range;
> +       ggtt->base.insert_page = mock_insert_page;
> +       ggtt->base.insert_entries = mock_insert_entries;
> +       ggtt->base.bind_vma = mock_bind_vma;
> +       ggtt->base.unbind_vma = mock_unbind_vma;
> +       ggtt->base.cleanup = mock_remove;
> +
> +       i915_address_space_init(&ggtt->base, i915, "global");
> +}
Perhaps add a mock_fini_ggtt for device_release, with a call to
i915_address_space_fini ?

With that:
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 08/19] drm/i915: Mock a GGTT for self-testing
  2017-01-09 15:16   ` Matthew Auld
@ 2017-01-10 12:33     ` Chris Wilson
  0 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2017-01-10 12:33 UTC (permalink / raw)
  To: Matthew Auld; +Cc: Intel Graphics Development

On Mon, Jan 09, 2017 at 03:16:19PM +0000, Matthew Auld wrote:
> On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> > @@ -90,19 +91,40 @@ struct drm_i915_private *mock_gem_device(void)
> >         i915->drm.pdev = pdev;
> >         i915->drm.dev_private = i915;
> >
> > +       drm_mode_config_init(&i915->drm);
> > +
> Why do we need this for mocking the ggtt ?

Because evicting from the GTT asks the question
intel_has_pending_fb_unpin()

Better add a comment because I had forgotten why as well.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 17/19] drm/i915: Add some mock tests for dmabuf interop
  2016-12-20 13:08 ` [RFCv2 17/19] drm/i915: Add some mock tests for dmabuf interop Chris Wilson
@ 2017-01-10 19:12   ` Matthew Auld
  0 siblings, 0 replies; 33+ messages in thread
From: Matthew Auld @ 2017-01-10 19:12 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Check that we can create both dmabuf and objects from dmabuf.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_gem_dmabuf.c             |   5 +
>  drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c   | 297 +++++++++++++++++++++
>  .../gpu/drm/i915/selftests/i915_mock_selftests.h   |   1 +
>  drivers/gpu/drm/i915/selftests/mock_dmabuf.c       | 176 ++++++++++++
>  drivers/gpu/drm/i915/selftests/mock_dmabuf.h       |  43 +++
>  5 files changed, 522 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
>  create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.c
>  create mode 100644 drivers/gpu/drm/i915/selftests/mock_dmabuf.h
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> index d037adcda6f2..3e276eee0450 100644
> --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> @@ -307,3 +307,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
>
>         return ERR_PTR(ret);
>  }
> +
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +#include "selftests/mock_dmabuf.c"
> +#include "selftests/i915_gem_dmabuf.c"
> +#endif
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
> new file mode 100644
> index 000000000000..115c477978f7
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_dmabuf.c
> @@ -0,0 +1,297 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "i915_selftest.h"
> +
> +#include "mock_gem_device.h"
> +#include "mock_dmabuf.h"
> +
> +static int igt_dmabuf_export(void *arg)
> +{
> +       struct drm_i915_private *i915 = arg;
> +       struct drm_i915_gem_object *obj;
> +       struct dma_buf *dmabuf;
> +       int err;
> +
> +       obj = i915_gem_object_create(i915, PAGE_SIZE);
> +       if (IS_ERR(obj))
> +               return PTR_ERR(obj);
> +
> +       dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
> +       if (IS_ERR(dmabuf)) {
> +               pr_err("i915_gem_prime_export failed with err=%d\n",
> +                      (int)PTR_ERR(dmabuf));
> +               err = PTR_ERR(dmabuf);
> +               goto err;
> +       }
> +
> +       err = 0;
> +       dma_buf_put(dmabuf);
> +err:
> +       i915_gem_object_put(obj);
> +       return err;
> +}
> +
> +static int igt_dmabuf_import_self(void *arg)
> +{
> +       struct drm_i915_private *i915 = arg;
> +       struct drm_i915_gem_object *obj;
> +       struct drm_gem_object *import;
> +       struct dma_buf *dmabuf;
> +       int err;
> +
> +       obj = i915_gem_object_create(i915, PAGE_SIZE);
> +       if (IS_ERR(obj))
> +               return PTR_ERR(obj);
> +
> +       dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
> +       if (IS_ERR(dmabuf)) {
> +               pr_err("i915_gem_prime_export failed with err=%d\n",
> +                      (int)PTR_ERR(dmabuf));
> +               err = PTR_ERR(dmabuf);
> +               goto err;
> +       }
> +
> +       import = i915_gem_prime_import(&i915->drm, dmabuf);
> +       if (IS_ERR(import)) {
> +               pr_err("i915_gem_prime_import failed with err=%d\n",
> +                      (int)PTR_ERR(import));
> +               err = PTR_ERR(import);
> +               goto err_dmabuf;
> +       }
> +
> +       if (import != &obj->base) {
> +               pr_err("i915_gem_prime_import created a new object!\n");
> +               err = -EINVAL;
> +               goto err_import;
> +       }
> +
> +       err = 0;
> +err_import:
> +       i915_gem_object_put(to_intel_bo(import));
> +err_dmabuf:
> +       dma_buf_put(dmabuf);
> +err:
> +       i915_gem_object_put(obj);
> +       return err;
> +}
> +
> +static int igt_dmabuf_import(void *arg)
> +{
> +       struct drm_i915_private *i915 = arg;
> +       struct drm_i915_gem_object *obj;
> +       struct dma_buf *dmabuf;
> +       void *obj_map, *dma_map;
> +       u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff };
> +       int err, i;
> +
> +       dmabuf = mock_dmabuf(1);
This looks like it's going to blow up if it returns NULL, which it
can. See the other call site too.

> +       if (IS_ERR(dmabuf))
> +               return PTR_ERR(dmabuf);
> +
> +       obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
> +       if (IS_ERR(obj)) {
> +               pr_err("i915_gem_prime_import failed with err=%d\n",
> +                      (int)PTR_ERR(obj));
> +               err = PTR_ERR(obj);
> +               goto err_dmabuf;
> +       }
> +
> +       if (obj->base.dev != &i915->drm) {
> +               pr_err("i915_gem_prime_import created a non-i915 object!\n");
> +               err = -EINVAL;
> +               goto err_obj;
> +       }
> +
> +       if (obj->base.size != PAGE_SIZE) {
> +               pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n",
> +                      (long long)obj->base.size, PAGE_SIZE);
> +               err = -EINVAL;
> +               goto err_obj;
> +       }
> +
> +       dma_map = dma_buf_vmap(dmabuf);
> +       if (!dma_map) {
> +               pr_err("dma_buf_vmap failed\n");
> +               err = -ENOMEM;
> +               goto err_obj;
> +       }
> +
> +       if (0) {
> +               /* Can not yet map dmabuf */
> +               obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB);
> +               if (IS_ERR(obj_map)) {
> +                       err = PTR_ERR(obj_map);
> +                       pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
> +                       goto err_dma_map;
> +               }
> +
> +               for (i = 0; i < ARRAY_SIZE(pattern); i++) {
> +                       memset(dma_map, pattern[i], PAGE_SIZE);
> +                       if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) {
> +                               err = -EINVAL;
> +                               pr_err("imported vmap not all set to %x!\n", pattern[i]);
> +                               i915_gem_object_unpin_map(obj);
> +                               goto err_dma_map;
> +                       }
> +               }
> +
> +               for (i = 0; i < ARRAY_SIZE(pattern); i++) {
> +                       memset(obj_map, pattern[i], PAGE_SIZE);
> +                       if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) {
> +                               err = -EINVAL;
> +                               pr_err("exported vmap not all set to %x!\n", pattern[i]);
> +                               i915_gem_object_unpin_map(obj);
> +                               goto err_dma_map;
> +                       }
> +               }
i915_gem_object_unpin_map(obj);

> +       }
> +
> +       err = 0;
> +err_dma_map:
> +       dma_buf_vunmap(dmabuf, dma_map);
> +err_obj:
> +       i915_gem_object_put(obj);
> +err_dmabuf:
> +       dma_buf_put(dmabuf);
> +       return err;
> +}
> +
> +static int igt_dmabuf_import_ownership(void *arg)
> +{
> +       struct drm_i915_private *i915 = arg;
> +       struct drm_i915_gem_object *obj;
> +       struct dma_buf *dmabuf;
> +       void *ptr;
> +       int err;
> +
> +       dmabuf = mock_dmabuf(1);
> +       if (IS_ERR(dmabuf))
> +               return PTR_ERR(dmabuf);
> +
> +       ptr = dma_buf_vmap(dmabuf);
> +       if (!ptr) {
> +               pr_err("dma_buf_vmap failed\n");
> +               err = -ENOMEM;
> +               goto err_dmabuf;
> +       }
> +
> +       memset(ptr, 0xc5, PAGE_SIZE);
> +       dma_buf_vunmap(dmabuf, ptr);
> +
> +       obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
> +       if (IS_ERR(obj)) {
> +               pr_err("i915_gem_prime_import failed with err=%d\n",
> +                      (int)PTR_ERR(obj));
> +               err = PTR_ERR(obj);
> +               goto err_dmabuf;
> +       }
> +
> +       dma_buf_put(dmabuf);
> +
> +       err = i915_gem_object_pin_pages(obj);
> +       if (err) {
> +               pr_err("i915_gem_object_pin_pages failed with err=%d\n", err);
> +               goto err_obj;
> +       }
> +
> +       err = 0;
> +       i915_gem_object_unpin_pages(obj);
> +err_obj:
> +       i915_gem_object_put(obj);
> +       return err;
> +
> +err_dmabuf:
> +       dma_buf_put(dmabuf);
> +       return err;
> +}
> +
> +static int igt_dmabuf_export_vmap(void *arg)
> +{
> +       struct drm_i915_private *i915 = arg;
> +       struct drm_i915_gem_object *obj;
> +       struct dma_buf *dmabuf;
> +       void *ptr;
> +       int err;
> +
> +       obj = i915_gem_object_create(i915, PAGE_SIZE);
> +       if (IS_ERR(obj))
> +               return PTR_ERR(obj);
> +
> +       dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
> +       if (IS_ERR(dmabuf)) {
> +               pr_err("i915_gem_prime_export failed with err=%d\n",
> +                      (int)PTR_ERR(dmabuf));
> +               err = PTR_ERR(dmabuf);
> +               goto err_obj;
> +       }
> +       i915_gem_object_put(obj);
> +
> +       ptr = dma_buf_vmap(dmabuf);
> +       if (IS_ERR(ptr)) {
> +               err = PTR_ERR(ptr);
> +               pr_err("dma_buf_vmap failed with err=%d\n", err);
> +               goto err;
> +       }
> +
> +       if(memchr_inv(ptr, 0, dmabuf->size)) {
> +               pr_err("Exported object no initialiased to zero!\n");
s/no initialiased/not initialised/

> +               err = -EINVAL;
> +               goto err;
> +       }
> +
> +       memset(ptr, 0xc5, dmabuf->size);
> +
> +       err = 0;
> +       dma_buf_vunmap(dmabuf, ptr);
> +err:
> +       dma_buf_put(dmabuf);
> +       return err;
> +
> +err_obj:
> +       i915_gem_object_put(obj);
> +       return err;
> +}
> +
> +int i915_gem_dmabuf_selftest(void)
> +{
> +       static const struct i915_subtest tests[] = {
> +               SUBTEST(igt_dmabuf_export),
> +               SUBTEST(igt_dmabuf_import_self),
> +               SUBTEST(igt_dmabuf_import),
> +               SUBTEST(igt_dmabuf_import_ownership),
> +               SUBTEST(igt_dmabuf_export_vmap),
> +       };
> +       struct drm_i915_private *i915;
> +       int err;
> +
> +       i915 = mock_gem_device();
> +       if (!i915)
> +               return -ENOMEM;
> +
> +       err = i915_subtests(tests, i915);
> +
> +       drm_dev_unref(&i915->drm);
> +       return err;
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
> index 390af5cd895e..417bcfa3cdba 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
> +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
> @@ -14,3 +14,4 @@ selftest(uncore, intel_uncore_mock_selftests)
>  selftest(breadcrumbs, intel_breadcrumbs_selftest)
>  selftest(requests, i915_gem_request_selftest)
>  selftest(objects, i915_gem_object_selftests)
> +selftest(dmabuf, i915_gem_dmabuf_selftest)
> diff --git a/drivers/gpu/drm/i915/selftests/mock_dmabuf.c b/drivers/gpu/drm/i915/selftests/mock_dmabuf.c
> new file mode 100644
> index 000000000000..515691779540
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/mock_dmabuf.c
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "mock_dmabuf.h"
> +
> +static struct sg_table *mock_map_dma_buf(struct dma_buf_attachment *attachment,
> +                                        enum dma_data_direction dir)
> +{
> +       struct mock_dmabuf *mock = to_mock(attachment->dmabuf);
> +       struct sg_table *st;
> +       struct scatterlist *sg;
> +       int i, err;
> +
> +       st = kmalloc(sizeof(*st), GFP_KERNEL);
> +       if (!st)
> +               return ERR_PTR(-ENOMEM);
> +
> +       err = sg_alloc_table(st, mock->npages, GFP_KERNEL);
> +       if (err)
> +               goto err_free;
> +
> +       sg = st->sgl;
> +       for (i = 0; i < mock->npages; i++) {
> +               sg_set_page(sg, mock->pages[i], PAGE_SIZE, 0);
> +               sg = sg_next(sg);
> +       }
> +
> +       if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
> +               err = -ENOMEM;
> +               goto err_st;
> +       }
> +
> +       return st;
> +
> +err_st:
> +       sg_free_table(st);
> +err_free:
> +       kfree(st);
> +       return ERR_PTR(err);
> +}
> +
> +static void mock_unmap_dma_buf(struct dma_buf_attachment *attachment,
> +                              struct sg_table *st,
> +                              enum dma_data_direction dir)
> +{
> +       dma_unmap_sg(attachment->dev, st->sgl, st->nents, dir);
> +       sg_free_table(st);
> +       kfree(st);
> +}
> +
> +static void mock_dmabuf_release(struct dma_buf *dma_buf)
> +{
> +       struct mock_dmabuf *mock = to_mock(dma_buf);
> +       int i;
> +
> +       for (i = 0; i < mock->npages; i++)
> +               put_page(mock->pages[i]);
> +
> +       kfree(mock);
> +}
> +
> +static void *mock_dmabuf_vmap(struct dma_buf *dma_buf)
> +{
> +       struct mock_dmabuf *mock = to_mock(dma_buf);
> +
> +       return vm_map_ram(mock->pages, mock->npages, 0, PAGE_KERNEL);
> +}
> +
> +static void mock_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
> +{
> +       struct mock_dmabuf *mock = to_mock(dma_buf);
> +
> +       vm_unmap_ram(vaddr, mock->npages);
> +}
> +
> +static void *mock_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
> +{
> +       struct mock_dmabuf *mock = to_mock(dma_buf);
> +
> +       return kmap_atomic(mock->pages[page_num]);
> +}
> +
> +static void mock_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
> +{
> +       kunmap_atomic(addr);
> +}
> +
> +static void *mock_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
> +{
> +       struct mock_dmabuf *mock = to_mock(dma_buf);
> +
> +       return kmap(mock->pages[page_num]);
> +}
> +
> +static void mock_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
> +{
> +       struct mock_dmabuf *mock = to_mock(dma_buf);
> +
> +       return kunmap(mock->pages[page_num]);
> +}
> +
> +static int mock_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
> +{
> +       return -ENODEV;
> +}
> +
> +static const struct dma_buf_ops mock_dmabuf_ops =  {
> +       .map_dma_buf = mock_map_dma_buf,
> +       .unmap_dma_buf = mock_unmap_dma_buf,
> +       .release = mock_dmabuf_release,
> +       .kmap = mock_dmabuf_kmap,
> +       .kmap_atomic = mock_dmabuf_kmap_atomic,
> +       .kunmap = mock_dmabuf_kunmap,
> +       .kunmap_atomic = mock_dmabuf_kunmap_atomic,
> +       .mmap = mock_dmabuf_mmap,
> +       .vmap = mock_dmabuf_vmap,
> +       .vunmap = mock_dmabuf_vunmap,
> +};
> +
> +static struct dma_buf *mock_dmabuf(int npages)
> +{
> +       struct mock_dmabuf *mock;
> +       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> +       struct dma_buf *dmabuf;
> +       int i;
> +
> +       mock = kmalloc(sizeof(*mock) + npages * sizeof(struct page *),
> +                      GFP_KERNEL);
> +       if (!mock)
> +               return ERR_PTR(-ENOMEM);
> +
> +       mock->npages = npages;
> +       for (i = 0; i < npages; i++) {
> +               mock->pages[i] = alloc_page(GFP_KERNEL);
> +               if (!mock->pages[i])
> +                       goto err;
> +       }
> +
> +       exp_info.ops = &mock_dmabuf_ops;
> +       exp_info.size = npages * PAGE_SIZE;
> +       exp_info.flags = O_CLOEXEC;
> +       exp_info.priv = mock;
> +
> +       dmabuf = dma_buf_export(&exp_info);
> +       if (IS_ERR(dmabuf))
> +               goto err;
> +
> +       return dmabuf;
> +
> +err:
> +       while (i--)
> +               put_page(mock->pages[i]);
> +       kfree(mock);
> +       return NULL;
> +}
> diff --git a/drivers/gpu/drm/i915/selftests/mock_dmabuf.h b/drivers/gpu/drm/i915/selftests/mock_dmabuf.h
> new file mode 100644
> index 000000000000..bb5aaebcc80e
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/mock_dmabuf.h
> @@ -0,0 +1,43 @@
> +
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef __MOCK_DMABUF_H__
> +#define __MOCK_DMABUF_H__
> +
> +#include "mock_dmabuf.h"
> +
> +struct dma_buf;
> +
> +struct mock_dmabuf {
> +       int npages;
> +       struct page *pages[];
> +};
> +
> +static struct mock_dmabuf *to_mock(struct dma_buf *buf)
> +{
> +       return buf->priv;
We forward declare struct dma_buf, and yet we can access the priv member here ?

Otherwise:
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 18/19] drm/i915: Add initial selftests for i915_gem_gtt
  2016-12-20 13:08 ` [RFCv2 18/19] drm/i915: Add initial selftests for i915_gem_gtt Chris Wilson
@ 2017-01-10 19:32   ` Matthew Auld
  0 siblings, 0 replies; 33+ messages in thread
From: Matthew Auld @ 2017-01-10 19:32 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Simple starting point for adding seltests for i915_gem_gtt, first
> try creating a ppGTT and filling it.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 19/19] drm/i915: Initial selftests for exercising eviction
  2016-12-20 13:08 ` [RFCv2 19/19] drm/i915: Initial selftests for exercising eviction Chris Wilson
@ 2017-01-10 19:49   ` Matthew Auld
  0 siblings, 0 replies; 33+ messages in thread
From: Matthew Auld @ 2017-01-10 19:49 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Very simple tests to just ask eviction to find some free space in a full
> GTT and one with some available space.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_gem_evict.c              |   4 +
>  drivers/gpu/drm/i915/selftests/i915_gem_evict.c    | 237 +++++++++++++++++++++
>  .../gpu/drm/i915/selftests/i915_mock_selftests.h   |   1 +
>  3 files changed, 242 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/selftests/i915_gem_evict.c
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
> index f92f63e8749a..c01a9dd6298c 100644
> --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> @@ -383,3 +383,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
>
>         return 0;
>  }
> +
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +#include "selftests/i915_gem_evict.c"
> +#endif
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> new file mode 100644
> index 000000000000..c31e6a6c98cd
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> @@ -0,0 +1,237 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "i915_selftest.h"
> +
> +#include "mock_gem_device.h"
> +
> +static int populate_ggtt(struct drm_i915_private *i915)
> +{
> +       struct drm_i915_gem_object *obj;
> +       u64 size;
> +
> +       for (size = 0; size < i915->ggtt.base.total; size += PAGE_SIZE) {
> +               struct i915_vma *vma;
> +
> +               obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
> +               if (IS_ERR(obj))
> +                       return PTR_ERR(obj);
> +
> +               vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
> +               if (IS_ERR(vma))
> +                       return PTR_ERR(vma);
> +       }
> +
> +       if (!list_empty(&i915->mm.unbound_list)) {
> +               size = 0;
> +               list_for_each_entry(obj, &i915->mm.unbound_list, global_link)
> +                       size++;
> +
> +               pr_err("Found %lld objects unbound!\n", size);
> +               return -EINVAL;
> +       }
> +
> +       if (list_empty(&i915->ggtt.base.inactive_list)) {
> +               pr_err("No objects on the GGTT inactive list!\n");
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static void unpin_ggtt(struct drm_i915_private *i915)
> +{
> +       struct i915_vma *vma;
> +
> +       list_for_each_entry(vma, &i915->ggtt.base.inactive_list, vm_link)
> +               i915_vma_unpin(vma);
> +}
> +
> +static void cleanup_objects(struct drm_i915_private *i915)
> +{
> +       struct drm_i915_gem_object *obj, *on;
> +
> +       list_for_each_entry_safe(obj, on, &i915->mm.unbound_list, global_link)
> +               i915_gem_object_put(obj);
> +
> +       list_for_each_entry_safe(obj, on, &i915->mm.bound_list, global_link)
> +               i915_gem_object_put(obj);
> +
> +       mutex_unlock(&i915->drm.struct_mutex);
> +
> +       rcu_barrier();
> +       while (flush_work(&i915->mm.free_work))
> +               rcu_barrier();
i915_gem_drain_freed_objects(i915), likewise for device_release ?

Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 01/19] drm/i915: Provide a hook for selftests
  2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
                   ` (18 preceding siblings ...)
  2016-12-20 14:16 ` ✓ Fi.CI.BAT: success for series starting with [RFCv2,01/19] drm/i915: Provide a hook for selftests Patchwork
@ 2017-01-11 18:17 ` Tvrtko Ursulin
  2017-01-11 18:34   ` Chris Wilson
  19 siblings, 1 reply; 33+ messages in thread
From: Tvrtko Ursulin @ 2017-01-11 18:17 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 20/12/2016 13:07, Chris Wilson wrote:
> Some pieces of code are independent of hardware but are very tricky to
> exercise through the normal userspace ABI or via debugfs hooks. Being
> able to create mock unit tests and execute them through CI is vital.
> Start by adding a central point where we can execute unit tests and
> a parameter to enable them. This is disabled by default as the
> expectation is that these tests will occasionally explode.
>
> To facilitate integration with igt, any parameter beginning with
> i915.igt__ is interpreted as a subtest executable independently via
> igt/drv_selftest.
>
> Two classes of selftests are recognised: mock unit tests and integration
> tests. Mock unit tests are run as soon as the module is loaded, before
> the device is probed. At that point there is no driver instantiated and
> all hw interactions must be "mocked". This is very useful for writing
> universal tests to exercise code not typically run on a broad range of
> architectures. Alternatively, you can hook into the late selftests and
> run when the device has been instantiated - hw interactions are real.
>
> v2: Add a macro for compiling conditional code for mock objects inside
> real objects.
> v3: Differentiate between mock unit tests and late integration test.
> v4: List the tests in natural order, use igt to sort after modparam.
> v5: s/late/live/
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> #v1
> ---
>  drivers/gpu/drm/i915/Kconfig.debug                 |  15 ++
>  drivers/gpu/drm/i915/Makefile                      |   3 +
>  drivers/gpu/drm/i915/i915_pci.c                    |  19 +-
>  drivers/gpu/drm/i915/i915_selftest.h               |  91 +++++++++
>  .../gpu/drm/i915/selftests/i915_live_selftests.h   |  11 +
>  .../gpu/drm/i915/selftests/i915_mock_selftests.h   |  11 +
>  drivers/gpu/drm/i915/selftests/i915_selftest.c     | 222 +++++++++++++++++++++
>  7 files changed, 371 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/i915/i915_selftest.h
>  create mode 100644 drivers/gpu/drm/i915/selftests/i915_live_selftests.h
>  create mode 100644 drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
>  create mode 100644 drivers/gpu/drm/i915/selftests/i915_selftest.c
>
> diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
> index 598551dbf62c..de051502e891 100644
> --- a/drivers/gpu/drm/i915/Kconfig.debug
> +++ b/drivers/gpu/drm/i915/Kconfig.debug
> @@ -26,6 +26,7 @@ config DRM_I915_DEBUG
>          select DRM_DEBUG_MM if DRM=y
>  	select DRM_DEBUG_MM_SELFTEST
>  	select DRM_I915_SW_FENCE_DEBUG_OBJECTS
> +	select DRM_I915_SELFTEST
>          default n
>          help
>            Choose this option to turn on extra driver debugging that may affect
> @@ -59,3 +60,17 @@ config DRM_I915_SW_FENCE_DEBUG_OBJECTS
>            Recommended for driver developers only.
>
>            If in doubt, say "N".
> +
> +config DRM_I915_SELFTEST
> +	bool "Enable selftests upon driver load"
> +	depends on DRM_I915
> +	default n
> +	help
> +	  Choose this option to allow the driver to perform selftests upon
> +	  loading; also requires the i915.selftest=1 module parameter. To
> +	  exit the module after running the selftests (i.e. to prevent normal
> +	  module initialisation afterwards) use i915.selftest=-1.
> +
> +	  Recommended for driver developers only.
> +
> +	  If in doubt, say "N".
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 5196509e71cf..461aeb44a9ad 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -3,6 +3,7 @@
>  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>
>  subdir-ccflags-$(CONFIG_DRM_I915_WERROR) := -Werror
> +subdir-ccflags-$(CONFIG_DRM_I915_SELFTEST) := -I$(src) -I$(src)/selftests
>  subdir-ccflags-y += \
>  	$(call as-instr,movntdqa (%eax)$(comma)%xmm0,-DCONFIG_AS_MOVNTDQA)
>
> @@ -114,6 +115,8 @@ i915-y += dvo_ch7017.o \
>
>  # Post-mortem debug and GPU hang state capture
>  i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
> +i915-$(CONFIG_DRM_I915_SELFTEST) += \
> +	selftests/i915_selftest.o
>
>  # virtual gpu code
>  i915-y += i915_vgpu.o
> diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
> index 9885458b0fb8..3d416d142573 100644
> --- a/drivers/gpu/drm/i915/i915_pci.c
> +++ b/drivers/gpu/drm/i915/i915_pci.c
> @@ -27,6 +27,7 @@
>  #include <linux/vga_switcheroo.h>
>
>  #include "i915_drv.h"
> +#include "i915_selftest.h"
>
>  #define GEN_DEFAULT_PIPEOFFSETS \
>  	.pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \
> @@ -477,6 +478,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>  {
>  	struct intel_device_info *intel_info =
>  		(struct intel_device_info *) ent->driver_data;
> +	int err;
>
>  	if (IS_ALPHA_SUPPORT(intel_info) && !i915.alpha_support) {
>  		DRM_INFO("The driver support for your hardware in this kernel version is alpha quality\n"
> @@ -500,7 +502,17 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	if (vga_switcheroo_client_probe_defer(pdev))
>  		return -EPROBE_DEFER;
>
> -	return i915_driver_load(pdev, ent);
> +	err = i915_driver_load(pdev, ent);
> +	if (err)
> +		return err;
> +
> +	err = i915_live_selftests(pdev);
> +	if (err) {
> +		i915_driver_unload(pci_get_drvdata(pdev));
> +		return err > 0 ? -ENOTTY : err;
> +	}
> +
> +	return 0;
>  }
>
>  static void i915_pci_remove(struct pci_dev *pdev)
> @@ -522,6 +534,11 @@ static struct pci_driver i915_pci_driver = {
>  static int __init i915_init(void)
>  {
>  	bool use_kms = true;
> +	int err;
> +
> +	err = i915_mock_selftests();
> +	if (err)
> +		return err > 0 ? 0 : err;

Am I again confused by the return codes? :) Module param of -1 will 
result in i915_mock_selftests returning 1, which here translates to 0 so 
it won't abort the load like it should.

>
>  	/*
>  	 * Enable KMS by default, unless explicitly overriden by
> diff --git a/drivers/gpu/drm/i915/i915_selftest.h b/drivers/gpu/drm/i915/i915_selftest.h
> new file mode 100644
> index 000000000000..6b3d1192e092
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_selftest.h
> @@ -0,0 +1,91 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#ifndef __I915_SELFTEST_H__
> +#define __I915_SELFTEST_H__
> +
> +struct pci_dev;
> +struct drm_i915_private;
> +
> +struct i915_selftest {
> +	unsigned long timeout_jiffies;
> +	unsigned int timeout_ms;
> +	unsigned int random_seed;
> +	int mock;
> +	int live;
> +};
> +
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +extern struct i915_selftest i915_selftest;
> +
> +int i915_mock_selftests(void);
> +int i915_live_selftests(struct pci_dev *pdev);
> +
> +/* We extract the function declarations from i915_mock_selftests.h and
> + * i915_live_selftests.h Add your unit test declarations there!
> + *
> + * Mock unit tests are run very early upon module load, before the driver
> + * is probed. All hardware interactions, as well as other subsystems, must
> + * be "mocked".
> + *
> + * Late unit tests are run after the driver is loaded - all hardware
> + * interactions are real.
> + */
> +#define selftest(name, func) int func(void);
> +#include "i915_mock_selftests.h"
> +#undef selftest
> +#define selftest(name, func) int func(struct drm_i915_private *i915);
> +#include "i915_live_selftests.h"
> +#undef selftest
> +
> +struct i915_subtest {
> +	int (*func)(void *data);
> +	const char *name;
> +};
> +
> +int __i915_subtests(const char *caller,
> +		    const struct i915_subtest *st,
> +		    int count,
> +		    void *data);
> +#define i915_subtests(T, data) \
> +	__i915_subtests(__func__, T, ARRAY_SIZE(T), data)
> +
> +#define SUBTEST(x) { x, #x }
> +
> +#define I915_SELFTEST_DECLARE(x) x
> +#define I915_SELFTEST_ONLY(x) unlikely(x)
> +
> +#else /* !IS_ENABLED(CONFIG_DRM_I915_SELFTEST) */
> +
> +static inline int i915_mock_selftests(void) { return 0; }
> +static inline int i915_live_selftests(struct pci_dev *pdev) { return 0; }
> +
> +#define I915_SELFTEST_DECLARE(x)
> +#define I915_SELFTEST_ONLY(x) 0
> +
> +#endif
> +
> +#define I915_SELFTEST_TIMEOUT(name__) \
> +	unsigned long name__ = jiffies + i915_selftest.timeout_jiffies
> +
> +#endif /* !__I915_SELFTEST_H__ */
> diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> new file mode 100644
> index 000000000000..f3e17cb10e05
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> @@ -0,0 +1,11 @@
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as subtest__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * The function should be of type int function(void). It may be conditionally
> + * compiled using #if IS_ENABLED(DRM_I915_SELFTEST).
> + *
> + * Tests are executed in order by igt/drv_selftest
> + */
> +selftest(sanitycheck, i915_live_sanitycheck) /* keep first (igt selfcheck) */
> diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
> new file mode 100644
> index 000000000000..69e97a2ba4a6
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h
> @@ -0,0 +1,11 @@
> +/* List each unit test as selftest(name, function)
> + *
> + * The name is used as both an enum and expanded as subtest__name to create
> + * a module parameter. It must be unique and legal for a C identifier.
> + *
> + * The function should be of type int function(void). It may be conditionally
> + * compiled using #if IS_ENABLED(DRM_I915_SELFTEST).
> + *
> + * Tests are executed in order by igt/drv_selftest
> + */
> +selftest(sanitycheck, i915_mock_sanitycheck) /* keep first (igt selfcheck) */
> diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c
> new file mode 100644
> index 000000000000..4876f974edb8
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c
> @@ -0,0 +1,222 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#include <linux/random.h>
> +
> +#include "i915_drv.h"
> +#include "i915_selftest.h"
> +
> +struct i915_selftest i915_selftest __read_mostly = {
> +	.timeout_ms = 1000,
> +};
> +
> +int i915_mock_sanitycheck(void)
> +{
> +	pr_info("i915: %s() - ok!\n", __func__);
> +	return 0;
> +}
> +
> +int i915_live_sanitycheck(struct drm_i915_private *i915)
> +{
> +	pr_info("%s: %s() - ok!\n", i915->drm.driver->name, __func__);
> +	return 0;
> +}
> +
> +enum {
> +#define selftest(name, func) mock_##name,
> +#include "i915_mock_selftests.h"
> +#undef selftest
> +};
> +enum {
> +#define selftest(name, func) live_##name,
> +#include "i915_live_selftests.h"
> +#undef selftest
> +};
> +
> +struct selftest {
> +	bool enabled;
> +	const char *name;
> +	union {
> +		int (*mock)(void);
> +		int (*live)(struct drm_i915_private *);
> +	};
> +};
> +
> +#define selftest(n, f) [mock_##n] = { .name = #n, .mock = f },
> +static struct selftest mock_selftests[] = {
> +#include "i915_mock_selftests.h"
> +};
> +#undef selftest
> +
> +#define selftest(n, f) [live_##n] = { .name = #n, .live = f },
> +static struct selftest live_selftests[] = {
> +#include "i915_live_selftests.h"
> +};
> +#undef selftest
> +
> +/* Embed the line number into the parameter name so that we can order tests */
> +#define selftest(n, func) selftest_0(n, func, param(n))
> +#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), mock_##n))
> +#define selftest_0(n, func, id) \
> +module_param_named(id, mock_selftests[mock_##n].enabled, bool, 0400);
> +#include "i915_mock_selftests.h"
> +#undef selftest_0
> +#undef param
> +
> +#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), live_##n))
> +#define selftest_0(n, func, id) \
> +module_param_named(id, live_selftests[live_##n].enabled, bool, 0400);
> +#include "i915_live_selftests.h"
> +#undef selftest_0
> +#undef param
> +#undef selftest
> +
> +static void set_default_test_all(struct selftest *st, unsigned long count)
> +{
> +	unsigned long i;
> +
> +	for (i = 0; i < count; i++)
> +		if (st[i].enabled)
> +			return;
> +
> +	for (i = 0; i < count; i++)
> +		st[i].enabled = true;
> +}

unsigned int should be enough for everyone! :) (i & count)

> +
> +static int run_selftests(const char *name,
> +			 struct selftest *st,
> +			 unsigned long count,
> +			 void *data)
> +{
> +	int err = 0;
> +

If I got it right:

/* Make sure both live and mock run with the same seed if ran one after 
another. */

? just not sure what happens if user sets zero.

> +	while (!i915_selftest.random_seed)
> +		i915_selftest.random_seed = get_random_int();
> +
> +	i915_selftest.timeout_jiffies =
> +		i915_selftest.timeout_ms ?
> +		msecs_to_jiffies_timeout(i915_selftest.timeout_ms) :
> +		MAX_SCHEDULE_TIMEOUT;
> +
> +	set_default_test_all(st, count);
> +
> +	pr_info("i915: Performing %s selftests with st_random_seed=%x and st_timeout=%u\n",
> +		name, i915_selftest.random_seed, i915_selftest.timeout_ms);
> +
> +	/* Tests are listed in order in i915_*_selftests.h */
> +	for (; count--; st++) {
> +		if (!st->enabled)
> +			continue;
> +
> +		cond_resched();
> +		if (signal_pending(current))
> +			return -EINTR;
> +
> +		pr_debug("i915: Running %s\n", st->name);
> +		if (data)
> +			err = st->live(data);
> +		else
> +			err = st->mock();
> +		if (err)
> +			break;
> +	}
> +
> +	if (WARN(err > 0 || err == -ENOTTY,
> +		 "%s returned %d, conflicting with selftest's magic values!\n",
> +		 st->name, err))
> +		err = -1;
> +
> +	rcu_barrier();

Why this?

> +	return err;
> +}
> +
> +#define run_selftests(x, data) \
> +	(run_selftests)(#x, x##_selftests, ARRAY_SIZE(x##_selftests), data)
> +
> +int i915_mock_selftests(void)
> +{
> +	int err;
> +
> +	if (!i915_selftest.mock)
> +		return 0;
> +
> +	err = run_selftests(mock, NULL);
> +	if (err)
> +		return err;
> +
> +	if (i915_selftest.mock < 0)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +int i915_live_selftests(struct pci_dev *pdev)
> +{
> +	int err;
> +
> +	if (!i915_selftest.live)
> +		return 0;
> +
> +	err = run_selftests(live, to_i915(pci_get_drvdata(pdev)));
> +	if (err)
> +		return err;
> +
> +	if (i915_selftest.live < 0)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +int __i915_subtests(const char *caller,
> +		    const struct i915_subtest *st,
> +		    int count,
> +		    void *data)
> +{
> +	int err;
> +
> +	for (; count--; st++) {
> +		cond_resched();
> +		if (signal_pending(current))
> +			return -EINTR;
> +
> +		pr_debug("i915: Running %s/%s\n", caller, st->name);
> +		err = st->func(data);
> +		if (err) {
> +			if (err != -EINTR)
> +				pr_err("i915/%s: %s failed with error %d\n",
> +				       caller, st->name, err);
> +			return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +module_param_named(st_random_seed, i915_selftest.random_seed, uint, 0400);
> +module_param_named(st_timeout, i915_selftest.timeout_ms, uint, 0400);
> +
> +module_param_named_unsafe(mock_selftests, i915_selftest.mock, int, 0400);
> +MODULE_PARM_DESC(mock_selftests, "Run selftests before loading, using mock hardware (0:disabled [default], 1:run tests then load driver, -1:run tests then exit module)");
> +
> +module_param_named_unsafe(live_selftests, i915_selftest.live, int, 0400);
> +MODULE_PARM_DESC(live_selftests, "Run selftests after driver initialisation on the live system (0:disabled [default], 1:run tests then continue, -1:run tests then exit module)");
>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 14/19] drm/i915: Move uncore selfchecks to live selftest infrastructure
  2016-12-20 13:08 ` [RFCv2 14/19] drm/i915: Move uncore selfchecks to live selftest infrastructure Chris Wilson
@ 2017-01-11 18:21   ` Matthew Auld
  0 siblings, 0 replies; 33+ messages in thread
From: Matthew Auld @ 2017-01-11 18:21 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Now that the kselftest infrastructure exists, put it to use and add to
> it the existing consistency checks on the fw register lookup tables.
>
> v2: s/tabke/table/
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 15/19] drm/i915: Test all fw tables during mock selftests
  2016-12-20 13:08 ` [RFCv2 15/19] drm/i915: Test all fw tables during mock selftests Chris Wilson
@ 2017-01-11 18:22   ` Matthew Auld
  0 siblings, 0 replies; 33+ messages in thread
From: Matthew Auld @ 2017-01-11 18:22 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> In addition to just testing the fw table we load, during the initial
> mock testing we can test that all tables are valid (so the testing is
> not limited to just the platforms that load that particular table).
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains
  2016-12-20 13:08 ` [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains Chris Wilson
@ 2017-01-11 18:25   ` Matthew Auld
  2017-01-11 18:39     ` Chris Wilson
  2017-01-11 19:08   ` Matthew Auld
  1 sibling, 1 reply; 33+ messages in thread
From: Matthew Auld @ 2017-01-11 18:25 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Add a late selftest that walks over all forcewake registers (those below
> 0x40000) and checks intel_uncore_forcewake_for_reg() that the look
> exists and we having the matching powerwells.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/selftests/intel_uncore.c | 47 +++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
> index c18fddb12d00..c9f90514500f 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
> @@ -107,6 +107,49 @@ int intel_uncore_mock_selftests(void)
>         return 0;
>  }
>
> +static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_priv)
> +{
> +#define FW_RANGE 0x40000
> +       unsigned long *valid;
> +       u32 offset;
> +       int err;
> +
> +       valid = kzalloc(BITS_TO_LONGS(FW_RANGE) * sizeof(*valid),
> +                       GFP_TEMPORARY);
> +       if (!valid)
> +               return -ENOMEM;
> +
> +       intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
> +
> +       check_for_unclaimed_mmio(dev_priv);
> +       for (offset = 0; offset < FW_RANGE; offset += 4) {
> +               i915_reg_t reg = { offset };
> +
> +               (void)I915_READ_FW(reg);
> +               if (!check_for_unclaimed_mmio(dev_priv))
> +                       set_bit(offset, valid);
> +       }
> +
> +       intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> +
> +       for_each_set_bit(offset, valid, FW_RANGE) {
> +               i915_reg_t reg = { offset };
> +
> +               intel_uncore_forcewake_reset(dev_priv, false);
> +               check_for_unclaimed_mmio(dev_priv);
hmm, what do we need this for ?

> +
> +               (void)I915_READ(reg);
> +               if (check_for_unclaimed_mmio(dev_priv)) {
> +                       pr_err("Unclaimed mmio read to register 0x%04x\n",
> +                              offset);
> +                       err = -EINVAL;
> +               }
> +       }
> +
> +       kfree(valid);
> +       return err;
> +}
> +
>  int intel_uncore_live_selftests(struct drm_i915_private *i915)
>  {
>         int err;
> @@ -118,5 +161,9 @@ int intel_uncore_live_selftests(struct drm_i915_private *i915)
>         if (err)
>                 return err;
>
> +       err = intel_uncore_check_forcewake_domains(i915);
> +       if (err)
> +               return err;
> +
>         return 0;
>  }
> --
> 2.11.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 01/19] drm/i915: Provide a hook for selftests
  2017-01-11 18:17 ` [RFCv2 01/19] " Tvrtko Ursulin
@ 2017-01-11 18:34   ` Chris Wilson
  0 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2017-01-11 18:34 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Wed, Jan 11, 2017 at 06:17:48PM +0000, Tvrtko Ursulin wrote:
> On 20/12/2016 13:07, Chris Wilson wrote:
> >@@ -522,6 +534,11 @@ static struct pci_driver i915_pci_driver = {
> > static int __init i915_init(void)
> > {
> > 	bool use_kms = true;
> >+	int err;
> >+
> >+	err = i915_mock_selftests();
> >+	if (err)
> >+		return err > 0 ? 0 : err;
> 
> Am I again confused by the return codes? :) Module param of -1 will
> result in i915_mock_selftests returning 1, which here translates to
> 0 so it won't abort the load like it should.

I had to give up on that for silent passing and do the remove from
userspace on success instead. Returning anything other than 0 causes noise
in dmesg. That I can live with after an error during the selftest, since
dmesg should also contain more details on the test failure.

If i915.mock_selftests=-1 then we run the tests and stop. We just leave
the module loaded even though it hasn't bound to any pci devices. :|
igt/drv_selftest and kselftests/gpu/i915.sh then unload the module.

> >+static void set_default_test_all(struct selftest *st, unsigned long count)
> >+{
> >+	unsigned long i;
> >+
> >+	for (i = 0; i < count; i++)
> >+		if (st[i].enabled)
> >+			return;
> >+
> >+	for (i = 0; i < count; i++)
> >+		st[i].enabled = true;
> >+}
> 
> unsigned int should be enough for everyone! :) (i & count)

Such shortsightedness!

> >+static int run_selftests(const char *name,
> >+			 struct selftest *st,
> >+			 unsigned long count,
> >+			 void *data)
> >+{
> >+	int err = 0;
> >+
> 
> If I got it right:
> 
> /* Make sure both live and mock run with the same seed if ran one
> after another. */

Yes, choose the seed once, run every selected test with the same seed.
 
> ? just not sure what happens if user sets zero.

I wasn't such if 0 was a valid seed, so I wasn't caring too much if the
user did i915.st_random_seed=0. They will see the pr_info() and go
wtf, and hopefully don't do that again.

> >+	while (!i915_selftest.random_seed)
> >+		i915_selftest.random_seed = get_random_int();
> >+
> >+	i915_selftest.timeout_jiffies =
> >+		i915_selftest.timeout_ms ?
> >+		msecs_to_jiffies_timeout(i915_selftest.timeout_ms) :
> >+		MAX_SCHEDULE_TIMEOUT;
> >+
> >+	set_default_test_all(st, count);
> >+
> >+	pr_info("i915: Performing %s selftests with st_random_seed=%x and st_timeout=%u\n",
> >+		name, i915_selftest.random_seed, i915_selftest.timeout_ms);
> >+
> >+	/* Tests are listed in order in i915_*_selftests.h */
> >+	for (; count--; st++) {
> >+		if (!st->enabled)
> >+			continue;
> >+
> >+		cond_resched();
> >+		if (signal_pending(current))
> >+			return -EINTR;
> >+
> >+		pr_debug("i915: Running %s\n", st->name);
> >+		if (data)
> >+			err = st->live(data);
> >+		else
> >+			err = st->mock();
> >+		if (err)
> >+			break;
> >+	}
> >+
> >+	if (WARN(err > 0 || err == -ENOTTY,
> >+		 "%s returned %d, conflicting with selftest's magic values!\n",
> >+		 st->name, err))
> >+		err = -1;
> >+
> >+	rcu_barrier();
> 
> Why this?

Paranoia for the tests aborting without the barrier, as we can't rely on
module_unload providing it since we may go on to load the driver as
normal.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains
  2017-01-11 18:25   ` Matthew Auld
@ 2017-01-11 18:39     ` Chris Wilson
  0 siblings, 0 replies; 33+ messages in thread
From: Chris Wilson @ 2017-01-11 18:39 UTC (permalink / raw)
  To: Matthew Auld; +Cc: Intel Graphics Development

On Wed, Jan 11, 2017 at 06:25:59PM +0000, Matthew Auld wrote:
> On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> > +       for_each_set_bit(offset, valid, FW_RANGE) {
> > +               i915_reg_t reg = { offset };
> > +
> > +               intel_uncore_forcewake_reset(dev_priv, false);
> > +               check_for_unclaimed_mmio(dev_priv);
> hmm, what do we need this for ?

It clears the debug register before every test - so that we know the
only thing the debug register is complaining about is the I915_READ()
sandwiched in between. The reset is there to ensure that the fw is
turned off and the timer disabled, so that we have a vanilla state
every time with the powerwell off. Hopefully.
 
> > +
> > +               (void)I915_READ(reg);
> > +               if (check_for_unclaimed_mmio(dev_priv)) {

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains
  2016-12-20 13:08 ` [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains Chris Wilson
  2017-01-11 18:25   ` Matthew Auld
@ 2017-01-11 19:08   ` Matthew Auld
  1 sibling, 0 replies; 33+ messages in thread
From: Matthew Auld @ 2017-01-11 19:08 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Intel Graphics Development

On 20 December 2016 at 13:08, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Add a late selftest that walks over all forcewake registers (those below
> 0x40000) and checks intel_uncore_forcewake_for_reg() that the look
I don't see where we use intel_uncore_forcewake_for_reg() ?
look ?

> exists and we having the matching powerwells.
s/having/have/

>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/selftests/intel_uncore.c | 47 +++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
> index c18fddb12d00..c9f90514500f 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
> @@ -107,6 +107,49 @@ int intel_uncore_mock_selftests(void)
>         return 0;
>  }
>
> +static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_priv)
> +{
> +#define FW_RANGE 0x40000
> +       unsigned long *valid;
> +       u32 offset;
> +       int err;
> +
> +       valid = kzalloc(BITS_TO_LONGS(FW_RANGE) * sizeof(*valid),
> +                       GFP_TEMPORARY);
> +       if (!valid)
> +               return -ENOMEM;
> +
> +       intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
> +
> +       check_for_unclaimed_mmio(dev_priv);
> +       for (offset = 0; offset < FW_RANGE; offset += 4) {
> +               i915_reg_t reg = { offset };
> +
> +               (void)I915_READ_FW(reg);
> +               if (!check_for_unclaimed_mmio(dev_priv))
> +                       set_bit(offset, valid);
> +       }
> +
> +       intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> +
> +       for_each_set_bit(offset, valid, FW_RANGE) {
> +               i915_reg_t reg = { offset };
> +
> +               intel_uncore_forcewake_reset(dev_priv, false);
> +               check_for_unclaimed_mmio(dev_priv);
> +
> +               (void)I915_READ(reg);
> +               if (check_for_unclaimed_mmio(dev_priv)) {
> +                       pr_err("Unclaimed mmio read to register 0x%04x\n",
> +                              offset);
> +                       err = -EINVAL;
> +               }
> +       }
> +
> +       kfree(valid);
> +       return err;
#undef FW_RANGE

Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2017-01-11 19:08 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-20 13:07 [RFCv2 01/19] drm/i915: Provide a hook for selftests Chris Wilson
2016-12-20 13:07 ` [RFCv2 02/19] kselftests: Exercise hw-independent mock tests for i915.ko Chris Wilson
2016-12-20 13:07 ` [RFCv2 03/19] drm/i915: Add some selftests for sg_table manipulation Chris Wilson
2016-12-20 13:07 ` [RFCv2 04/19] drm/i915: Add unit tests for the breadcrumb rbtree, insert/remove Chris Wilson
2016-12-20 13:08 ` [RFCv2 05/19] drm/i915: Add unit tests for the breadcrumb rbtree, completion Chris Wilson
2016-12-20 13:08 ` [RFCv2 06/19] drm/i915: Add unit tests for the breadcrumb rbtree, wakeups Chris Wilson
2016-12-20 13:08 ` [RFCv2 07/19] drm/i915: Mock the GEM device for self-testing Chris Wilson
2017-01-09 15:10   ` Matthew Auld
2016-12-20 13:08 ` [RFCv2 08/19] drm/i915: Mock a GGTT " Chris Wilson
2017-01-09 15:16   ` Matthew Auld
2017-01-10 12:33     ` Chris Wilson
2016-12-20 13:08 ` [RFCv2 09/19] drm/i915: Mock infrastructure for request emission Chris Wilson
2016-12-20 13:08 ` [RFCv2 10/19] drm/i915: Add selftests for i915_gem_request Chris Wilson
2016-12-20 13:08 ` [RFCv2 11/19] drm/i915: Add a simple request selftest for waiting Chris Wilson
2016-12-20 13:08 ` [RFCv2 12/19] drm/i915: Add a simple fence selftest to i915_gem_request Chris Wilson
2016-12-20 13:08 ` [RFCv2 13/19] drm/i915: Add selftests for object allocation, phys Chris Wilson
2016-12-20 13:08 ` [RFCv2 14/19] drm/i915: Move uncore selfchecks to live selftest infrastructure Chris Wilson
2017-01-11 18:21   ` Matthew Auld
2016-12-20 13:08 ` [RFCv2 15/19] drm/i915: Test all fw tables during mock selftests Chris Wilson
2017-01-11 18:22   ` Matthew Auld
2016-12-20 13:08 ` [RFCv2 16/19] drm/i915: Sanity check all registers for matching fw domains Chris Wilson
2017-01-11 18:25   ` Matthew Auld
2017-01-11 18:39     ` Chris Wilson
2017-01-11 19:08   ` Matthew Auld
2016-12-20 13:08 ` [RFCv2 17/19] drm/i915: Add some mock tests for dmabuf interop Chris Wilson
2017-01-10 19:12   ` Matthew Auld
2016-12-20 13:08 ` [RFCv2 18/19] drm/i915: Add initial selftests for i915_gem_gtt Chris Wilson
2017-01-10 19:32   ` Matthew Auld
2016-12-20 13:08 ` [RFCv2 19/19] drm/i915: Initial selftests for exercising eviction Chris Wilson
2017-01-10 19:49   ` Matthew Auld
2016-12-20 14:16 ` ✓ Fi.CI.BAT: success for series starting with [RFCv2,01/19] drm/i915: Provide a hook for selftests Patchwork
2017-01-11 18:17 ` [RFCv2 01/19] " Tvrtko Ursulin
2017-01-11 18:34   ` Chris Wilson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.