Merge tag 'drm-intel-next-2018-09-06-2' of git://anongit.freedesktop.org/drm/drm...
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / i915 / selftests / intel_guc.c
1 /*
2  * Copyright © 2017 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24
25 #include "../i915_selftest.h"
26
27 /* max doorbell number + negative test for each client type */
28 #define ATTEMPTS (GUC_NUM_DOORBELLS + GUC_CLIENT_PRIORITY_NUM)
29
30 static struct intel_guc_client *clients[ATTEMPTS];
31
32 static bool available_dbs(struct intel_guc *guc, u32 priority)
33 {
34         unsigned long offset;
35         unsigned long end;
36         u16 id;
37
38         /* first half is used for normal priority, second half for high */
39         offset = 0;
40         end = GUC_NUM_DOORBELLS / 2;
41         if (priority <= GUC_CLIENT_PRIORITY_HIGH) {
42                 offset = end;
43                 end += offset;
44         }
45
46         id = find_next_zero_bit(guc->doorbell_bitmap, end, offset);
47         if (id < end)
48                 return true;
49
50         return false;
51 }
52
53 static int check_all_doorbells(struct intel_guc *guc)
54 {
55         u16 db_id;
56
57         pr_info_once("Max number of doorbells: %d", GUC_NUM_DOORBELLS);
58         for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) {
59                 if (!doorbell_ok(guc, db_id)) {
60                         pr_err("doorbell %d, not ok\n", db_id);
61                         return -EIO;
62                 }
63         }
64
65         return 0;
66 }
67
68 static int ring_doorbell_nop(struct intel_guc_client *client)
69 {
70         struct guc_process_desc *desc = __get_process_desc(client);
71         int err;
72
73         client->use_nop_wqi = true;
74
75         spin_lock_irq(&client->wq_lock);
76
77         guc_wq_item_append(client, 0, 0, 0, 0);
78         guc_ring_doorbell(client);
79
80         spin_unlock_irq(&client->wq_lock);
81
82         client->use_nop_wqi = false;
83
84         /* if there are no issues GuC will update the WQ head and keep the
85          * WQ in active status
86          */
87         err = wait_for(READ_ONCE(desc->head) == READ_ONCE(desc->tail), 10);
88         if (err) {
89                 pr_err("doorbell %u ring failed!\n", client->doorbell_id);
90                 return -EIO;
91         }
92
93         if (desc->wq_status != WQ_STATUS_ACTIVE) {
94                 pr_err("doorbell %u ring put WQ in bad state (%u)!\n",
95                        client->doorbell_id, desc->wq_status);
96                 return -EIO;
97         }
98
99         return 0;
100 }
101
102 /*
103  * Basic client sanity check, handy to validate create_clients.
104  */
105 static int validate_client(struct intel_guc_client *client,
106                            int client_priority,
107                            bool is_preempt_client)
108 {
109         struct drm_i915_private *dev_priv = guc_to_i915(client->guc);
110         struct i915_gem_context *ctx_owner = is_preempt_client ?
111                         dev_priv->preempt_context : dev_priv->kernel_context;
112
113         if (client->owner != ctx_owner ||
114             client->engines != INTEL_INFO(dev_priv)->ring_mask ||
115             client->priority != client_priority ||
116             client->doorbell_id == GUC_DOORBELL_INVALID)
117                 return -EINVAL;
118         else
119                 return 0;
120 }
121
122 static bool client_doorbell_in_sync(struct intel_guc_client *client)
123 {
124         return !client || doorbell_ok(client->guc, client->doorbell_id);
125 }
126
127 /*
128  * Check that we're able to synchronize guc_clients with their doorbells
129  *
130  * We're creating clients and reserving doorbells once, at module load. During
131  * module lifetime, GuC, doorbell HW, and i915 state may go out of sync due to
132  * GuC being reset. In other words - GuC clients are still around, but the
133  * status of their doorbells may be incorrect. This is the reason behind
134  * validating that the doorbells status expected by the driver matches what the
135  * GuC/HW have.
136  */
137 static int igt_guc_clients(void *args)
138 {
139         struct drm_i915_private *dev_priv = args;
140         struct intel_guc *guc;
141         int err = 0;
142
143         GEM_BUG_ON(!HAS_GUC(dev_priv));
144         mutex_lock(&dev_priv->drm.struct_mutex);
145
146         guc = &dev_priv->guc;
147         if (!guc) {
148                 pr_err("No guc object!\n");
149                 err = -EINVAL;
150                 goto unlock;
151         }
152
153         err = check_all_doorbells(guc);
154         if (err)
155                 goto unlock;
156
157         /*
158          * Get rid of clients created during driver load because the test will
159          * recreate them.
160          */
161         guc_clients_destroy(guc);
162         if (guc->execbuf_client || guc->preempt_client) {
163                 pr_err("guc_clients_destroy lied!\n");
164                 err = -EINVAL;
165                 goto unlock;
166         }
167
168         err = guc_clients_create(guc);
169         if (err) {
170                 pr_err("Failed to create clients\n");
171                 goto unlock;
172         }
173         GEM_BUG_ON(!guc->execbuf_client);
174
175         err = validate_client(guc->execbuf_client,
176                               GUC_CLIENT_PRIORITY_KMD_NORMAL, false);
177         if (err) {
178                 pr_err("execbug client validation failed\n");
179                 goto out;
180         }
181
182         if (guc->preempt_client) {
183                 err = validate_client(guc->preempt_client,
184                                       GUC_CLIENT_PRIORITY_KMD_HIGH, true);
185                 if (err) {
186                         pr_err("preempt client validation failed\n");
187                         goto out;
188                 }
189         }
190
191         /* each client should now have reserved a doorbell */
192         if (!has_doorbell(guc->execbuf_client) ||
193             (guc->preempt_client && !has_doorbell(guc->preempt_client))) {
194                 pr_err("guc_clients_create didn't reserve doorbells\n");
195                 err = -EINVAL;
196                 goto out;
197         }
198
199         /* Now create the doorbells */
200         guc_clients_doorbell_init(guc);
201
202         /* each client should now have received a doorbell */
203         if (!client_doorbell_in_sync(guc->execbuf_client) ||
204             !client_doorbell_in_sync(guc->preempt_client)) {
205                 pr_err("failed to initialize the doorbells\n");
206                 err = -EINVAL;
207                 goto out;
208         }
209
210         /*
211          * Basic test - an attempt to reallocate a valid doorbell to the
212          * client it is currently assigned should not cause a failure.
213          */
214         err = guc_clients_doorbell_init(guc);
215         if (err)
216                 goto out;
217
218         /*
219          * Negative test - a client with no doorbell (invalid db id).
220          * After destroying the doorbell, the db id is changed to
221          * GUC_DOORBELL_INVALID and the firmware will reject any attempt to
222          * allocate a doorbell with an invalid id (db has to be reserved before
223          * allocation).
224          */
225         destroy_doorbell(guc->execbuf_client);
226         if (client_doorbell_in_sync(guc->execbuf_client)) {
227                 pr_err("destroy db did not work\n");
228                 err = -EINVAL;
229                 goto out;
230         }
231
232         unreserve_doorbell(guc->execbuf_client);
233
234         __create_doorbell(guc->execbuf_client);
235         err = __guc_allocate_doorbell(guc, guc->execbuf_client->stage_id);
236         if (err != -EIO) {
237                 pr_err("unexpected (err = %d)", err);
238                 goto out_db;
239         }
240
241         if (!available_dbs(guc, guc->execbuf_client->priority)) {
242                 pr_err("doorbell not available when it should\n");
243                 err = -EIO;
244                 goto out_db;
245         }
246
247 out_db:
248         /* clean after test */
249         __destroy_doorbell(guc->execbuf_client);
250         err = reserve_doorbell(guc->execbuf_client);
251         if (err) {
252                 pr_err("failed to reserve back the doorbell back\n");
253         }
254         err = create_doorbell(guc->execbuf_client);
255         if (err) {
256                 pr_err("recreate doorbell failed\n");
257                 goto out;
258         }
259
260 out:
261         /*
262          * Leave clean state for other test, plus the driver always destroy the
263          * clients during unload.
264          */
265         destroy_doorbell(guc->execbuf_client);
266         if (guc->preempt_client)
267                 destroy_doorbell(guc->preempt_client);
268         guc_clients_destroy(guc);
269         guc_clients_create(guc);
270         guc_clients_doorbell_init(guc);
271 unlock:
272         mutex_unlock(&dev_priv->drm.struct_mutex);
273         return err;
274 }
275
276 /*
277  * Create as many clients as number of doorbells. Note that there's already
278  * client(s)/doorbell(s) created during driver load, but this test creates
279  * its own and do not interact with the existing ones.
280  */
281 static int igt_guc_doorbells(void *arg)
282 {
283         struct drm_i915_private *dev_priv = arg;
284         struct intel_guc *guc;
285         int i, err = 0;
286         u16 db_id;
287
288         GEM_BUG_ON(!HAS_GUC(dev_priv));
289         mutex_lock(&dev_priv->drm.struct_mutex);
290
291         guc = &dev_priv->guc;
292         if (!guc) {
293                 pr_err("No guc object!\n");
294                 err = -EINVAL;
295                 goto unlock;
296         }
297
298         err = check_all_doorbells(guc);
299         if (err)
300                 goto unlock;
301
302         for (i = 0; i < ATTEMPTS; i++) {
303                 clients[i] = guc_client_alloc(dev_priv,
304                                               INTEL_INFO(dev_priv)->ring_mask,
305                                               i % GUC_CLIENT_PRIORITY_NUM,
306                                               dev_priv->kernel_context);
307
308                 if (!clients[i]) {
309                         pr_err("[%d] No guc client\n", i);
310                         err = -EINVAL;
311                         goto out;
312                 }
313
314                 if (IS_ERR(clients[i])) {
315                         if (PTR_ERR(clients[i]) != -ENOSPC) {
316                                 pr_err("[%d] unexpected error\n", i);
317                                 err = PTR_ERR(clients[i]);
318                                 goto out;
319                         }
320
321                         if (available_dbs(guc, i % GUC_CLIENT_PRIORITY_NUM)) {
322                                 pr_err("[%d] non-db related alloc fail\n", i);
323                                 err = -EINVAL;
324                                 goto out;
325                         }
326
327                         /* expected, ran out of dbs for this client type */
328                         continue;
329                 }
330
331                 /*
332                  * The check below is only valid because we keep a doorbell
333                  * assigned during the whole life of the client.
334                  */
335                 if (clients[i]->stage_id >= GUC_NUM_DOORBELLS) {
336                         pr_err("[%d] more clients than doorbells (%d >= %d)\n",
337                                i, clients[i]->stage_id, GUC_NUM_DOORBELLS);
338                         err = -EINVAL;
339                         goto out;
340                 }
341
342                 err = validate_client(clients[i],
343                                       i % GUC_CLIENT_PRIORITY_NUM, false);
344                 if (err) {
345                         pr_err("[%d] client_alloc sanity check failed!\n", i);
346                         err = -EINVAL;
347                         goto out;
348                 }
349
350                 db_id = clients[i]->doorbell_id;
351
352                 err = create_doorbell(clients[i]);
353                 if (err) {
354                         pr_err("[%d] Failed to create a doorbell\n", i);
355                         goto out;
356                 }
357
358                 /* doorbell id shouldn't change, we are holding the mutex */
359                 if (db_id != clients[i]->doorbell_id) {
360                         pr_err("[%d] doorbell id changed (%d != %d)\n",
361                                i, db_id, clients[i]->doorbell_id);
362                         err = -EINVAL;
363                         goto out;
364                 }
365
366                 err = check_all_doorbells(guc);
367                 if (err)
368                         goto out;
369
370                 err = ring_doorbell_nop(clients[i]);
371                 if (err)
372                         goto out;
373         }
374
375 out:
376         for (i = 0; i < ATTEMPTS; i++)
377                 if (!IS_ERR_OR_NULL(clients[i])) {
378                         destroy_doorbell(clients[i]);
379                         guc_client_free(clients[i]);
380                 }
381 unlock:
382         mutex_unlock(&dev_priv->drm.struct_mutex);
383         return err;
384 }
385
386 int intel_guc_live_selftest(struct drm_i915_private *dev_priv)
387 {
388         static const struct i915_subtest tests[] = {
389                 SUBTEST(igt_guc_clients),
390                 SUBTEST(igt_guc_doorbells),
391         };
392
393         if (!USES_GUC_SUBMISSION(dev_priv))
394                 return 0;
395
396         return i915_subtests(tests, dev_priv);
397 }