Commit 4c2ba55b authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

drm: kselftest for drm_mm and color adjustment

Check that after applying the driver's color adjustment, fitting of the
node and its alignment are still correct.

v2: s/no_color_touching/separate_adjacent_colors/
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20161222083641.2691-18-chris@chris-wilson.co.uk
parent 05ab3c2e
......@@ -18,3 +18,4 @@ selftest(align64, igt_align64)
selftest(evict, igt_evict)
selftest(evict_range, igt_evict_range)
selftest(topdown, igt_topdown)
selftest(color, igt_color)
......@@ -1671,6 +1671,189 @@ static int igt_topdown(void *ignored)
return ret;
}
static void separate_adjacent_colors(const struct drm_mm_node *node,
unsigned long color,
u64 *start,
u64 *end)
{
if (node->allocated && node->color != color)
++*start;
node = list_next_entry(node, node_list);
if (node->allocated && node->color != color)
--*end;
}
static bool colors_abutt(const struct drm_mm_node *node)
{
if (!node->hole_follows &&
list_next_entry(node, node_list)->allocated) {
pr_err("colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n",
node->color, node->start, node->size,
list_next_entry(node, node_list)->color,
list_next_entry(node, node_list)->start,
list_next_entry(node, node_list)->size);
return true;
}
return false;
}
static int igt_color(void *ignored)
{
const unsigned int count = min(4096u, max_iterations);
const struct insert_mode *mode;
struct drm_mm mm;
struct drm_mm_node *node, *nn;
unsigned int n;
int ret = -EINVAL, err;
/* Color adjustment complicates everything. First we just check
* that when we insert a node we apply any color_adjustment callback.
* The callback we use should ensure that there is a gap between
* any two nodes, and so after each insertion we check that those
* holes are inserted and that they are preserved.
*/
drm_mm_init(&mm, 0, U64_MAX);
for (n = 1; n <= count; n++) {
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node) {
ret = -ENOMEM;
goto out;
}
if (!expect_insert(&mm, node,
n, 0, n,
&insert_modes[0])) {
pr_err("insert failed, step %d\n", n);
kfree(node);
goto out;
}
}
drm_mm_for_each_node_safe(node, nn, &mm) {
if (node->color != node->size) {
pr_err("invalid color stored: expected %lld, found %ld\n",
node->size, node->color);
goto out;
}
drm_mm_remove_node(node);
kfree(node);
}
/* Now, let's start experimenting with applying a color callback */
mm.color_adjust = separate_adjacent_colors;
for (mode = insert_modes; mode->name; mode++) {
u64 last;
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node) {
ret = -ENOMEM;
goto out;
}
node->size = 1 + 2*count;
node->color = node->size;
err = drm_mm_reserve_node(&mm, node);
if (err) {
pr_err("initial reserve failed!\n");
ret = err;
goto out;
}
last = node->start + node->size;
for (n = 1; n <= count; n++) {
int rem;
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node) {
ret = -ENOMEM;
goto out;
}
node->start = last;
node->size = n + count;
node->color = node->size;
err = drm_mm_reserve_node(&mm, node);
if (err != -ENOSPC) {
pr_err("reserve %d did not report color overlap! err=%d\n",
n, err);
goto out;
}
node->start += n + 1;
rem = misalignment(node, n + count);
node->start += n + count - rem;
err = drm_mm_reserve_node(&mm, node);
if (err) {
pr_err("reserve %d failed, err=%d\n", n, err);
ret = err;
goto out;
}
last = node->start + node->size;
}
for (n = 1; n <= count; n++) {
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node) {
ret = -ENOMEM;
goto out;
}
if (!expect_insert(&mm, node,
n, n, n,
mode)) {
pr_err("%s insert failed, step %d\n",
mode->name, n);
kfree(node);
goto out;
}
}
drm_mm_for_each_node_safe(node, nn, &mm) {
u64 rem;
if (node->color != node->size) {
pr_err("%s invalid color stored: expected %lld, found %ld\n",
mode->name, node->size, node->color);
goto out;
}
if (colors_abutt(node))
goto out;
div64_u64_rem(node->start, node->size, &rem);
if (rem) {
pr_err("%s colored node misaligned, start=%llx expected alignment=%lld [rem=%lld]\n",
mode->name, node->start, node->size, rem);
goto out;
}
drm_mm_remove_node(node);
kfree(node);
}
}
ret = 0;
out:
drm_mm_for_each_node_safe(node, nn, &mm) {
drm_mm_remove_node(node);
kfree(node);
}
drm_mm_takedown(&mm);
return ret;
}
#include "drm_selftest.c"
static int __init test_drm_mm_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment