blob: 434320061d9e284a27b007827267de123977f940 [file] [log] [blame]
Chris Wilson50f00332016-12-22 08:36:09 +00001/*
2 * Test cases for the drm_mm range manager
3 */
4
5#define pr_fmt(fmt) "drm_mm: " fmt
6
7#include <linux/module.h>
8#include <linux/prime_numbers.h>
9#include <linux/slab.h>
10#include <linux/random.h>
11#include <linux/vmalloc.h>
12
13#include <drm/drm_mm.h>
14
15#include "../lib/drm_random.h"
16
17#define TESTS "drm_mm_selftests.h"
18#include "drm_selftest.h"
19
20static unsigned int random_seed;
21static unsigned int max_iterations = 8192;
22static unsigned int max_prime = 128;
23
24static int igt_sanitycheck(void *ignored)
25{
26 pr_info("%s - ok!\n", __func__);
27 return 0;
28}
29
Chris Wilson393b50f2016-12-22 08:36:10 +000030static bool assert_no_holes(const struct drm_mm *mm)
31{
32 struct drm_mm_node *hole;
33 u64 hole_start, hole_end;
34 unsigned long count;
35
36 count = 0;
37 drm_mm_for_each_hole(hole, mm, hole_start, hole_end)
38 count++;
39 if (count) {
40 pr_err("Expected to find no holes (after reserve), found %lu instead\n", count);
41 return false;
42 }
43
44 drm_mm_for_each_node(hole, mm) {
45 if (hole->hole_follows) {
46 pr_err("Hole follows node, expected none!\n");
47 return false;
48 }
49 }
50
51 return true;
52}
53
54static bool assert_one_hole(const struct drm_mm *mm, u64 start, u64 end)
55{
56 struct drm_mm_node *hole;
57 u64 hole_start, hole_end;
58 unsigned long count;
59 bool ok = true;
60
61 if (end <= start)
62 return true;
63
64 count = 0;
65 drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
66 if (start != hole_start || end != hole_end) {
67 if (ok)
68 pr_err("empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n",
69 hole_start, hole_end,
70 start, end);
71 ok = false;
72 }
73 count++;
74 }
75 if (count != 1) {
76 pr_err("Expected to find one hole, found %lu instead\n", count);
77 ok = false;
78 }
79
80 return ok;
81}
82
83static int igt_init(void *ignored)
84{
85 const unsigned int size = 4096;
86 struct drm_mm mm;
87 struct drm_mm_node tmp;
88 int ret = -EINVAL;
89
90 /* Start with some simple checks on initialising the struct drm_mm */
91 memset(&mm, 0, sizeof(mm));
92 if (drm_mm_initialized(&mm)) {
93 pr_err("zeroed mm claims to be initialized\n");
94 return ret;
95 }
96
97 memset(&mm, 0xff, sizeof(mm));
98 drm_mm_init(&mm, 0, size);
99 if (!drm_mm_initialized(&mm)) {
100 pr_err("mm claims not to be initialized\n");
101 goto out;
102 }
103
104 if (!drm_mm_clean(&mm)) {
105 pr_err("mm not empty on creation\n");
106 goto out;
107 }
108
109 /* After creation, it should all be one massive hole */
110 if (!assert_one_hole(&mm, 0, size)) {
111 ret = -EINVAL;
112 goto out;
113 }
114
115 memset(&tmp, 0, sizeof(tmp));
116 tmp.start = 0;
117 tmp.size = size;
118 ret = drm_mm_reserve_node(&mm, &tmp);
119 if (ret) {
120 pr_err("failed to reserve whole drm_mm\n");
121 goto out;
122 }
123
124 /* After filling the range entirely, there should be no holes */
125 if (!assert_no_holes(&mm)) {
126 ret = -EINVAL;
127 goto out;
128 }
129
130 /* And then after emptying it again, the massive hole should be back */
131 drm_mm_remove_node(&tmp);
132 if (!assert_one_hole(&mm, 0, size)) {
133 ret = -EINVAL;
134 goto out;
135 }
136
137out:
138 if (ret)
139 drm_mm_debug_table(&mm, __func__);
140 drm_mm_takedown(&mm);
141 return ret;
142}
143
Chris Wilson06df8ac2016-12-22 08:36:11 +0000144static int igt_debug(void *ignored)
145{
146 struct drm_mm mm;
147 struct drm_mm_node nodes[2];
148 int ret;
149
150 /* Create a small drm_mm with a couple of nodes and a few holes, and
151 * check that the debug iterator doesn't explode over a trivial drm_mm.
152 */
153
154 drm_mm_init(&mm, 0, 4096);
155
156 memset(nodes, 0, sizeof(nodes));
157 nodes[0].start = 512;
158 nodes[0].size = 1024;
159 ret = drm_mm_reserve_node(&mm, &nodes[0]);
160 if (ret) {
161 pr_err("failed to reserve node[0] {start=%lld, size=%lld)\n",
162 nodes[0].start, nodes[0].size);
163 return ret;
164 }
165
166 nodes[1].size = 1024;
167 nodes[1].start = 4096 - 512 - nodes[1].size;
168 ret = drm_mm_reserve_node(&mm, &nodes[1]);
169 if (ret) {
170 pr_err("failed to reserve node[1] {start=%lld, size=%lld)\n",
171 nodes[1].start, nodes[1].size);
172 return ret;
173 }
174
175 drm_mm_debug_table(&mm, __func__);
176 return 0;
177}
178
Chris Wilson50f00332016-12-22 08:36:09 +0000179#include "drm_selftest.c"
180
181static int __init test_drm_mm_init(void)
182{
183 int err;
184
185 while (!random_seed)
186 random_seed = get_random_int();
187
188 pr_info("Testing DRM range manger (struct drm_mm), with random_seed=0x%x max_iterations=%u max_prime=%u\n",
189 random_seed, max_iterations, max_prime);
190 err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
191
192 return err > 0 ? 0 : err;
193}
194
195static void __exit test_drm_mm_exit(void)
196{
197}
198
199module_init(test_drm_mm_init);
200module_exit(test_drm_mm_exit);
201
202module_param(random_seed, uint, 0400);
203module_param(max_iterations, uint, 0400);
204module_param(max_prime, uint, 0400);
205
206MODULE_AUTHOR("Intel Corporation");
207MODULE_LICENSE("GPL");