[PATCH 02/45] drm/i915: Provide a hook for selftests

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Tue Dec 6 12:33:04 UTC 2016


On 06/12/2016 00:12, 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 from 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.
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/Kconfig.debug    |  15 +++++
>  drivers/gpu/drm/i915/Makefile         |   1 +
>  drivers/gpu/drm/i915/i915_params.c    |   5 ++
>  drivers/gpu/drm/i915/i915_params.h    |   3 +
>  drivers/gpu/drm/i915/i915_pci.c       |   6 ++
>  drivers/gpu/drm/i915/i915_selftest.c  | 115 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_selftest.h  |  54 ++++++++++++++++
>  drivers/gpu/drm/i915/i915_selftests.h |  11 ++++
>  8 files changed, 210 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/i915_selftest.c
>  create mode 100644 drivers/gpu/drm/i915/i915_selftest.h
>  create mode 100644 drivers/gpu/drm/i915/i915_selftests.h
>
> diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
> index 597648c7a645..76af8774cf70 100644
> --- a/drivers/gpu/drm/i915/Kconfig.debug
> +++ b/drivers/gpu/drm/i915/Kconfig.debug
> @@ -25,6 +25,7 @@ config DRM_I915_DEBUG
>          select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
>          select DRM_DEBUG_MM if DRM=y
>  	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
> @@ -58,3 +59,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 3c30916727fb..7c3b4f0c836c 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -114,6 +114,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) += i915_selftest.o
>
>  # virtual gpu code
>  i915-y += i915_vgpu.o
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index 0e280fbd52f1..b66e38e66833 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -243,3 +243,8 @@ MODULE_PARM_DESC(enable_dpcd_backlight,
>  module_param_named(enable_gvt, i915.enable_gvt, bool, 0400);
>  MODULE_PARM_DESC(enable_gvt,
>  	"Enable support for Intel GVT-g graphics virtualization host support(default:false)");
> +
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +module_param_named_unsafe(selftest, i915.selftest, int, 0400);
> +MODULE_PARM_DESC(selftest, "Run selftests when loading (0:disabled [default], 1 run tests then load module, -1 run tests then exit module)");

Colon after 1 and -1 perhaps?

> +#endif
> diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
> index 8e433de04679..49ca8a6f9407 100644
> --- a/drivers/gpu/drm/i915/i915_params.h
> +++ b/drivers/gpu/drm/i915/i915_params.h
> @@ -28,6 +28,9 @@
>  #include <linux/cache.h> /* for __read_mostly */
>
>  struct i915_params {
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +	int selftest;
> +#endif
>  	int modeset;
>  	int panel_ignore_lid;
>  	int semaphores;
> diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
> index 389a33090707..1683adb845ee 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, \
> @@ -496,6 +497,11 @@ static struct pci_driver i915_pci_driver = {
>  static int __init i915_init(void)
>  {
>  	bool use_kms = true;
> +	int ret;
> +
> +	ret = i915_selftest();
> +	if (ret)
> +		return ret;
>
>  	/*
>  	 * Enable KMS by default, unless explicitly overriden by
> diff --git a/drivers/gpu/drm/i915/i915_selftest.c b/drivers/gpu/drm/i915/i915_selftest.c
> new file mode 100644
> index 000000000000..cbb0800b919e
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_selftest.c
> @@ -0,0 +1,115 @@
> +/*
> + * 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_drv.h"
> +#include "i915_selftest.h"
> +
> +int i915_selftest_sanitycheck(void)
> +{
> +	pr_info("i915: %s() - ok!\n", __func__);
> +	return 0;
> +}
> +
> +#define selftest(name, func) name,
> +enum {
> +#include "i915_selftests.h"
> +};
> +#undef selftest
> +
> +#define selftest(name, func) [name] = { #name, func },
> +static struct i915_selftest_subtest {
> +	const char *name;
> +	int (*func)(void);
> +	bool enabled;
> +} i915_selftests[] = {
> +#include "i915_selftests.h"
> +};
> +#undef selftest
> +
> +#define selftest(name, func) \
> +module_param_named(igt__##name, i915_selftests[name].enabled, bool, 0400);
> +#include "i915_selftests.h"
> +#undef selftest
> +
> +static void set_default_test_all(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(i915_selftests); i++)
> +		if (i915_selftests[i].enabled)
> +			return;
> +
> +	for (i = 0; i < ARRAY_SIZE(i915_selftests); i++)
> +		i915_selftests[i].enabled = true;
> +}
> +
> +int i915_selftest(void)
> +{
> +	int i;
> +
> +	if (!i915.selftest)
> +		return 0;
> +
> +	pr_info("i915: Performing selftests\n");
> +	set_default_test_all();
> +
> +	for (i = 0; i < ARRAY_SIZE(i915_selftests); i++) {
> +		int err;
> +
> +		if (!i915_selftests[i].enabled)
> +			continue;
> +
> +		pr_debug("i915: Running %s\n", i915_selftests[i].name);
> +		err = i915_selftests[i].func();
> +		if (err)
> +			return err;
> +	}
> +
> +	if (i915.selftest < 0)
> +		return -ENOTTY;
> +
> +	return 0;
> +}
> +
> +int __i915_subtests(const char *caller,
> +		    const struct i915_subtest *st,
> +		    int count,
> +		    void *data)
> +{
> +	int err;
> +
> +	while (count--) {
> +		pr_debug("i915: Running %s/%s\n", caller, st->name);
> +
> +		err = st->func(data);
> +		if (err) {
> +			pr_err("i915/%s: %s failed with error %d\n",
> +			       caller, st->name, err);
> +			return err;
> +		}
> +
> +		st++;
> +	}
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/i915/i915_selftest.h b/drivers/gpu/drm/i915/i915_selftest.h
> new file mode 100644
> index 000000000000..f1dc157a9461
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_selftest.h
> @@ -0,0 +1,54 @@
> +/*
> + * 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__
> +
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +int i915_selftest(void);
> +#else
> +static inline int i915_selftest(void) { return 0; }
> +#endif
> +
> +/* We extract the function declarations from i915_selftests.h.
> + * Add your unit tests there!

s/Add/Declare/ ?

> + */
> +#define selftest(name, func) int func(void);
> +#include "i915_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 }
> +
> +#endif /* __I915_SELFTEST_H__ */
> diff --git a/drivers/gpu/drm/i915/i915_selftests.h b/drivers/gpu/drm/i915/i915_selftests.h
> new file mode 100644
> index 000000000000..3f8015c8a520
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_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 reverse order by igt/drv_selftest
> + */
> +selftest(sanitycheck, i915_selftest_sanitycheck) /* keep last */
>

Some preprocessor trickery to navigate but looks ok. :)

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Regards,

Tvrtko


More information about the Intel-gfx-trybot mailing list