-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drm/i915: Provide a hook for selftests
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 live 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/ v6: s/unsigned long/unsigned int/ v7: Use igt_ prefixes for long helpers. v8: Deobfuscate macros overriding functions, stop using -I$(src) Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170213171558.20942-1-chris@chris-wilson.co.uk
- Loading branch information
Chris Wilson
committed
Feb 13, 2017
1 parent
2ae5573
commit 953c7f8
Showing
10 changed files
with
531 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* 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". | ||
* | ||
* Live unit tests are run after the driver is loaded - all hardware | ||
* interactions are real. | ||
*/ | ||
#define selftest(name, func) int func(void); | ||
#include "selftests/i915_mock_selftests.h" | ||
#undef selftest | ||
#define selftest(name, func) int func(struct drm_i915_private *i915); | ||
#include "selftests/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, | ||
unsigned 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 | ||
|
||
/* Using the i915_selftest_ prefix becomes a little unwieldy with the helpers. | ||
* Instead we use the igt_ shorthand, in reference to the intel-gpu-tools | ||
* suite of uabi test cases (which includes a test runner for our selftests). | ||
*/ | ||
|
||
#define IGT_TIMEOUT(name__) \ | ||
unsigned long name__ = jiffies + i915_selftest.timeout_jiffies | ||
|
||
__printf(2, 3) | ||
bool __igt_timeout(unsigned long timeout, const char *fmt, ...); | ||
|
||
#define igt_timeout(t, fmt, ...) \ | ||
__igt_timeout((t), KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) | ||
|
||
#endif /* !__I915_SELFTEST_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* 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(x) ({ \ | ||
struct rnd_state state__; \ | ||
prandom_seed_state(&state__, (x)); \ | ||
state__; \ | ||
}) | ||
|
||
#define I915_RND_STATE(name__) \ | ||
struct rnd_state name__ = I915_RND_STATE_INITIALIZER(i915_selftest.random_seed) | ||
|
||
#define I915_RND_SUBSTATE(name__, parent__) \ | ||
struct rnd_state name__ = I915_RND_STATE_INITIALIZER(prandom_u32_state(&(parent__))) | ||
|
||
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__ */ |
Oops, something went wrong.