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 #include "gem/i915_gem_pm.h"
27 
28 /* max doorbell number + negative test for each client type */
29 #define ATTEMPTS (GUC_NUM_DOORBELLS + GUC_CLIENT_PRIORITY_NUM)
30 
31 static struct intel_guc_client *clients[ATTEMPTS];
32 
33 static bool available_dbs(struct intel_guc *guc, u32 priority)
34 {
35 	unsigned long offset;
36 	unsigned long end;
37 	u16 id;
38 
39 	/* first half is used for normal priority, second half for high */
40 	offset = 0;
41 	end = GUC_NUM_DOORBELLS / 2;
42 	if (priority <= GUC_CLIENT_PRIORITY_HIGH) {
43 		offset = end;
44 		end += offset;
45 	}
46 
47 	id = find_next_zero_bit(guc->doorbell_bitmap, end, offset);
48 	if (id < end)
49 		return true;
50 
51 	return false;
52 }
53 
54 static int check_all_doorbells(struct intel_guc *guc)
55 {
56 	u16 db_id;
57 
58 	pr_info_once("Max number of doorbells: %d", GUC_NUM_DOORBELLS);
59 	for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) {
60 		if (!doorbell_ok(guc, db_id)) {
61 			pr_err("doorbell %d, not ok\n", db_id);
62 			return -EIO;
63 		}
64 	}
65 
66 	return 0;
67 }
68 
69 static int ring_doorbell_nop(struct intel_guc_client *client)
70 {
71 	struct guc_process_desc *desc = __get_process_desc(client);
72 	int err;
73 
74 	client->use_nop_wqi = true;
75 
76 	spin_lock_irq(&client->wq_lock);
77 
78 	guc_wq_item_append(client, 0, 0, 0, 0);
79 	guc_ring_doorbell(client);
80 
81 	spin_unlock_irq(&client->wq_lock);
82 
83 	client->use_nop_wqi = false;
84 
85 	/* if there are no issues GuC will update the WQ head and keep the
86 	 * WQ in active status
87 	 */
88 	err = wait_for(READ_ONCE(desc->head) == READ_ONCE(desc->tail), 10);
89 	if (err) {
90 		pr_err("doorbell %u ring failed!\n", client->doorbell_id);
91 		return -EIO;
92 	}
93 
94 	if (desc->wq_status != WQ_STATUS_ACTIVE) {
95 		pr_err("doorbell %u ring put WQ in bad state (%u)!\n",
96 		       client->doorbell_id, desc->wq_status);
97 		return -EIO;
98 	}
99 
100 	return 0;
101 }
102 
103 /*
104  * Basic client sanity check, handy to validate create_clients.
105  */
106 static int validate_client(struct intel_guc_client *client, int client_priority)
107 {
108 	if (client->priority != client_priority ||
109 	    client->doorbell_id == GUC_DOORBELL_INVALID)
110 		return -EINVAL;
111 	else
112 		return 0;
113 }
114 
115 static bool client_doorbell_in_sync(struct intel_guc_client *client)
116 {
117 	return !client || doorbell_ok(client->guc, client->doorbell_id);
118 }
119 
120 /*
121  * Check that we're able to synchronize guc_clients with their doorbells
122  *
123  * We're creating clients and reserving doorbells once, at module load. During
124  * module lifetime, GuC, doorbell HW, and i915 state may go out of sync due to
125  * GuC being reset. In other words - GuC clients are still around, but the
126  * status of their doorbells may be incorrect. This is the reason behind
127  * validating that the doorbells status expected by the driver matches what the
128  * GuC/HW have.
129  */
130 static int igt_guc_clients(void *args)
131 {
132 	struct drm_i915_private *dev_priv = args;
133 	intel_wakeref_t wakeref;
134 	struct intel_guc *guc;
135 	int err = 0;
136 
137 	GEM_BUG_ON(!HAS_GT_UC(dev_priv));
138 	mutex_lock(&dev_priv->drm.struct_mutex);
139 	wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
140 
141 	guc = &dev_priv->gt.uc.guc;
142 	if (!guc) {
143 		pr_err("No guc object!\n");
144 		err = -EINVAL;
145 		goto unlock;
146 	}
147 
148 	err = check_all_doorbells(guc);
149 	if (err)
150 		goto unlock;
151 
152 	/*
153 	 * Get rid of clients created during driver load because the test will
154 	 * recreate them.
155 	 */
156 	guc_clients_disable(guc);
157 	guc_clients_destroy(guc);
158 	if (guc->execbuf_client) {
159 		pr_err("guc_clients_destroy lied!\n");
160 		err = -EINVAL;
161 		goto unlock;
162 	}
163 
164 	err = guc_clients_create(guc);
165 	if (err) {
166 		pr_err("Failed to create clients\n");
167 		goto unlock;
168 	}
169 	GEM_BUG_ON(!guc->execbuf_client);
170 
171 	err = validate_client(guc->execbuf_client,
172 			      GUC_CLIENT_PRIORITY_KMD_NORMAL);
173 	if (err) {
174 		pr_err("execbug client validation failed\n");
175 		goto out;
176 	}
177 
178 	/* the client should now have reserved a doorbell */
179 	if (!has_doorbell(guc->execbuf_client)) {
180 		pr_err("guc_clients_create didn't reserve doorbells\n");
181 		err = -EINVAL;
182 		goto out;
183 	}
184 
185 	/* Now enable the clients */
186 	guc_clients_enable(guc);
187 
188 	/* each client should now have received a doorbell */
189 	if (!client_doorbell_in_sync(guc->execbuf_client)) {
190 		pr_err("failed to initialize the doorbells\n");
191 		err = -EINVAL;
192 		goto out;
193 	}
194 
195 	/*
196 	 * Basic test - an attempt to reallocate a valid doorbell to the
197 	 * client it is currently assigned should not cause a failure.
198 	 */
199 	err = create_doorbell(guc->execbuf_client);
200 
201 out:
202 	/*
203 	 * Leave clean state for other test, plus the driver always destroy the
204 	 * clients during unload.
205 	 */
206 	guc_clients_disable(guc);
207 	guc_clients_destroy(guc);
208 	guc_clients_create(guc);
209 	guc_clients_enable(guc);
210 unlock:
211 	intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
212 	mutex_unlock(&dev_priv->drm.struct_mutex);
213 	return err;
214 }
215 
216 /*
217  * Create as many clients as number of doorbells. Note that there's already
218  * client(s)/doorbell(s) created during driver load, but this test creates
219  * its own and do not interact with the existing ones.
220  */
221 static int igt_guc_doorbells(void *arg)
222 {
223 	struct drm_i915_private *dev_priv = arg;
224 	intel_wakeref_t wakeref;
225 	struct intel_guc *guc;
226 	int i, err = 0;
227 	u16 db_id;
228 
229 	GEM_BUG_ON(!HAS_GT_UC(dev_priv));
230 	mutex_lock(&dev_priv->drm.struct_mutex);
231 	wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
232 
233 	guc = &dev_priv->gt.uc.guc;
234 	if (!guc) {
235 		pr_err("No guc object!\n");
236 		err = -EINVAL;
237 		goto unlock;
238 	}
239 
240 	err = check_all_doorbells(guc);
241 	if (err)
242 		goto unlock;
243 
244 	for (i = 0; i < ATTEMPTS; i++) {
245 		clients[i] = guc_client_alloc(guc, i % GUC_CLIENT_PRIORITY_NUM);
246 
247 		if (!clients[i]) {
248 			pr_err("[%d] No guc client\n", i);
249 			err = -EINVAL;
250 			goto out;
251 		}
252 
253 		if (IS_ERR(clients[i])) {
254 			if (PTR_ERR(clients[i]) != -ENOSPC) {
255 				pr_err("[%d] unexpected error\n", i);
256 				err = PTR_ERR(clients[i]);
257 				goto out;
258 			}
259 
260 			if (available_dbs(guc, i % GUC_CLIENT_PRIORITY_NUM)) {
261 				pr_err("[%d] non-db related alloc fail\n", i);
262 				err = -EINVAL;
263 				goto out;
264 			}
265 
266 			/* expected, ran out of dbs for this client type */
267 			continue;
268 		}
269 
270 		/*
271 		 * The check below is only valid because we keep a doorbell
272 		 * assigned during the whole life of the client.
273 		 */
274 		if (clients[i]->stage_id >= GUC_NUM_DOORBELLS) {
275 			pr_err("[%d] more clients than doorbells (%d >= %d)\n",
276 			       i, clients[i]->stage_id, GUC_NUM_DOORBELLS);
277 			err = -EINVAL;
278 			goto out;
279 		}
280 
281 		err = validate_client(clients[i], i % GUC_CLIENT_PRIORITY_NUM);
282 		if (err) {
283 			pr_err("[%d] client_alloc sanity check failed!\n", i);
284 			err = -EINVAL;
285 			goto out;
286 		}
287 
288 		db_id = clients[i]->doorbell_id;
289 
290 		err = __guc_client_enable(clients[i]);
291 		if (err) {
292 			pr_err("[%d] Failed to create a doorbell\n", i);
293 			goto out;
294 		}
295 
296 		/* doorbell id shouldn't change, we are holding the mutex */
297 		if (db_id != clients[i]->doorbell_id) {
298 			pr_err("[%d] doorbell id changed (%d != %d)\n",
299 			       i, db_id, clients[i]->doorbell_id);
300 			err = -EINVAL;
301 			goto out;
302 		}
303 
304 		err = check_all_doorbells(guc);
305 		if (err)
306 			goto out;
307 
308 		err = ring_doorbell_nop(clients[i]);
309 		if (err)
310 			goto out;
311 	}
312 
313 out:
314 	for (i = 0; i < ATTEMPTS; i++)
315 		if (!IS_ERR_OR_NULL(clients[i])) {
316 			__guc_client_disable(clients[i]);
317 			guc_client_free(clients[i]);
318 		}
319 unlock:
320 	intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
321 	mutex_unlock(&dev_priv->drm.struct_mutex);
322 	return err;
323 }
324 
325 int intel_guc_live_selftest(struct drm_i915_private *dev_priv)
326 {
327 	static const struct i915_subtest tests[] = {
328 		SUBTEST(igt_guc_clients),
329 		SUBTEST(igt_guc_doorbells),
330 	};
331 
332 	if (!USES_GUC_SUBMISSION(dev_priv))
333 		return 0;
334 
335 	return i915_subtests(tests, dev_priv);
336 }
337