xref: /linux/drivers/gpu/drm/xe/xe_dma_buf.c (revision 6916d5703ddf9a38f1f6c2cc793381a24ee914c6)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include "xe_dma_buf.h"
7 
8 #include <kunit/test.h>
9 #include <linux/dma-buf.h>
10 #include <linux/pci-p2pdma.h>
11 
12 #include <drm/drm_device.h>
13 #include <drm/drm_prime.h>
14 #include <drm/ttm/ttm_tt.h>
15 
16 #include "tests/xe_test.h"
17 #include "xe_bo.h"
18 #include "xe_device.h"
19 #include "xe_pm.h"
20 #include "xe_ttm_vram_mgr.h"
21 #include "xe_vm.h"
22 
23 MODULE_IMPORT_NS("DMA_BUF");
24 
xe_dma_buf_attach(struct dma_buf * dmabuf,struct dma_buf_attachment * attach)25 static int xe_dma_buf_attach(struct dma_buf *dmabuf,
26 			     struct dma_buf_attachment *attach)
27 {
28 	struct drm_gem_object *obj = attach->dmabuf->priv;
29 
30 	if (attach->peer2peer &&
31 	    pci_p2pdma_distance(to_pci_dev(obj->dev->dev), attach->dev, false) < 0)
32 		attach->peer2peer = false;
33 
34 	if (!attach->peer2peer && !xe_bo_can_migrate(gem_to_xe_bo(obj), XE_PL_TT))
35 		return -EOPNOTSUPP;
36 
37 	xe_pm_runtime_get(to_xe_device(obj->dev));
38 	return 0;
39 }
40 
xe_dma_buf_detach(struct dma_buf * dmabuf,struct dma_buf_attachment * attach)41 static void xe_dma_buf_detach(struct dma_buf *dmabuf,
42 			      struct dma_buf_attachment *attach)
43 {
44 	struct drm_gem_object *obj = attach->dmabuf->priv;
45 
46 	xe_pm_runtime_put(to_xe_device(obj->dev));
47 }
48 
xe_dma_buf_pin(struct dma_buf_attachment * attach)49 static int xe_dma_buf_pin(struct dma_buf_attachment *attach)
50 {
51 	struct dma_buf *dmabuf = attach->dmabuf;
52 	struct drm_gem_object *obj = dmabuf->priv;
53 	struct xe_bo *bo = gem_to_xe_bo(obj);
54 	struct xe_device *xe = xe_bo_device(bo);
55 	struct drm_exec *exec = XE_VALIDATION_UNSUPPORTED;
56 	bool allow_vram = true;
57 	int ret;
58 
59 	list_for_each_entry(attach, &dmabuf->attachments, node) {
60 		if (!attach->peer2peer) {
61 			allow_vram = false;
62 			break;
63 		}
64 	}
65 
66 	if (xe_bo_is_pinned(bo) && !xe_bo_is_mem_type(bo, XE_PL_TT) &&
67 	    !(xe_bo_is_vram(bo) && allow_vram)) {
68 		drm_dbg(&xe->drm, "Can't migrate pinned bo for dma-buf pin.\n");
69 		return -EINVAL;
70 	}
71 
72 	if (!allow_vram) {
73 		ret = xe_bo_migrate(bo, XE_PL_TT, NULL, exec);
74 		if (ret) {
75 			if (ret != -EINTR && ret != -ERESTARTSYS)
76 				drm_dbg(&xe->drm,
77 					"Failed migrating dma-buf to TT memory: %pe\n",
78 					ERR_PTR(ret));
79 			return ret;
80 		}
81 	}
82 
83 	ret = xe_bo_pin_external(bo, !allow_vram, exec);
84 	xe_assert(xe, !ret);
85 
86 	return 0;
87 }
88 
xe_dma_buf_unpin(struct dma_buf_attachment * attach)89 static void xe_dma_buf_unpin(struct dma_buf_attachment *attach)
90 {
91 	struct drm_gem_object *obj = attach->dmabuf->priv;
92 	struct xe_bo *bo = gem_to_xe_bo(obj);
93 
94 	xe_bo_unpin_external(bo);
95 }
96 
xe_dma_buf_map(struct dma_buf_attachment * attach,enum dma_data_direction dir)97 static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
98 				       enum dma_data_direction dir)
99 {
100 	struct dma_buf *dma_buf = attach->dmabuf;
101 	struct drm_gem_object *obj = dma_buf->priv;
102 	struct xe_bo *bo = gem_to_xe_bo(obj);
103 	struct drm_exec *exec = XE_VALIDATION_UNSUPPORTED;
104 	struct sg_table *sgt;
105 	int r = 0;
106 
107 	if (!attach->peer2peer && !xe_bo_can_migrate(bo, XE_PL_TT))
108 		return ERR_PTR(-EOPNOTSUPP);
109 
110 	if (!xe_bo_is_pinned(bo)) {
111 		if (!attach->peer2peer)
112 			r = xe_bo_migrate(bo, XE_PL_TT, NULL, exec);
113 		else
114 			r = xe_bo_validate(bo, NULL, false, exec);
115 		if (r)
116 			return ERR_PTR(r);
117 	}
118 
119 	switch (bo->ttm.resource->mem_type) {
120 	case XE_PL_TT:
121 		sgt = drm_prime_pages_to_sg(obj->dev,
122 					    bo->ttm.ttm->pages,
123 					    obj->size >> PAGE_SHIFT);
124 		if (IS_ERR(sgt))
125 			return sgt;
126 
127 		if (dma_map_sgtable(attach->dev, sgt, dir,
128 				    DMA_ATTR_SKIP_CPU_SYNC))
129 			goto error_free;
130 		break;
131 
132 	case XE_PL_VRAM0:
133 	case XE_PL_VRAM1:
134 		r = xe_ttm_vram_mgr_alloc_sgt(xe_bo_device(bo),
135 					      bo->ttm.resource, 0,
136 					      bo->ttm.base.size, attach->dev,
137 					      dir, &sgt);
138 		if (r)
139 			return ERR_PTR(r);
140 		break;
141 	default:
142 		return ERR_PTR(-EINVAL);
143 	}
144 
145 	return sgt;
146 
147 error_free:
148 	sg_free_table(sgt);
149 	kfree(sgt);
150 	return ERR_PTR(-EBUSY);
151 }
152 
xe_dma_buf_unmap(struct dma_buf_attachment * attach,struct sg_table * sgt,enum dma_data_direction dir)153 static void xe_dma_buf_unmap(struct dma_buf_attachment *attach,
154 			     struct sg_table *sgt,
155 			     enum dma_data_direction dir)
156 {
157 	if (sg_page(sgt->sgl)) {
158 		dma_unmap_sgtable(attach->dev, sgt, dir, 0);
159 		sg_free_table(sgt);
160 		kfree(sgt);
161 	} else {
162 		xe_ttm_vram_mgr_free_sgt(attach->dev, dir, sgt);
163 	}
164 }
165 
xe_dma_buf_begin_cpu_access(struct dma_buf * dma_buf,enum dma_data_direction direction)166 static int xe_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
167 				       enum dma_data_direction direction)
168 {
169 	struct drm_gem_object *obj = dma_buf->priv;
170 	struct xe_bo *bo = gem_to_xe_bo(obj);
171 	bool reads =  (direction == DMA_BIDIRECTIONAL ||
172 		       direction == DMA_FROM_DEVICE);
173 	struct xe_validation_ctx ctx;
174 	struct drm_exec exec;
175 	int ret = 0;
176 
177 	if (!reads)
178 		return 0;
179 
180 	/* Can we do interruptible lock here? */
181 	xe_validation_guard(&ctx, &xe_bo_device(bo)->val, &exec, (struct xe_val_flags) {}, ret) {
182 		ret = drm_exec_lock_obj(&exec, &bo->ttm.base);
183 		drm_exec_retry_on_contention(&exec);
184 		if (ret)
185 			break;
186 
187 		ret = xe_bo_migrate(bo, XE_PL_TT, NULL, &exec);
188 		drm_exec_retry_on_contention(&exec);
189 		xe_validation_retry_on_oom(&ctx, &ret);
190 	}
191 
192 	/* If we failed, cpu-access takes place in current placement. */
193 	return 0;
194 }
195 
xe_dma_buf_release(struct dma_buf * dmabuf)196 static void xe_dma_buf_release(struct dma_buf *dmabuf)
197 {
198 	struct drm_gem_object *obj = dmabuf->priv;
199 	struct xe_bo *bo = gem_to_xe_bo(obj);
200 
201 	xe_bo_lock(bo, false);
202 	xe_bo_willneed_put_locked(bo);
203 	xe_bo_unlock(bo);
204 
205 	drm_gem_dmabuf_release(dmabuf);
206 }
207 
208 static const struct dma_buf_ops xe_dmabuf_ops = {
209 	.attach = xe_dma_buf_attach,
210 	.detach = xe_dma_buf_detach,
211 	.pin = xe_dma_buf_pin,
212 	.unpin = xe_dma_buf_unpin,
213 	.map_dma_buf = xe_dma_buf_map,
214 	.unmap_dma_buf = xe_dma_buf_unmap,
215 	.release = xe_dma_buf_release,
216 	.begin_cpu_access = xe_dma_buf_begin_cpu_access,
217 	.mmap = drm_gem_dmabuf_mmap,
218 	.vmap = drm_gem_dmabuf_vmap,
219 	.vunmap = drm_gem_dmabuf_vunmap,
220 };
221 
xe_gem_prime_export(struct drm_gem_object * obj,int flags)222 struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags)
223 {
224 	struct xe_bo *bo = gem_to_xe_bo(obj);
225 	struct dma_buf *buf;
226 	struct ttm_operation_ctx ctx = {
227 		.interruptible = true,
228 		.no_wait_gpu = true,
229 		/* We opt to avoid OOM on system pages allocations */
230 		.gfp_retry_mayfail = true,
231 		.allow_res_evict = false,
232 	};
233 	int ret;
234 
235 	if (bo->vm)
236 		return ERR_PTR(-EPERM);
237 
238 	/*
239 	 * Reject exporting purgeable BOs. DONTNEED BOs can be purged
240 	 * at any time, making the exported dma-buf unusable. Purged BOs
241 	 * have no backing store and are permanently invalid.
242 	 */
243 	ret = xe_bo_lock(bo, true);
244 	if (ret)
245 		return ERR_PTR(ret);
246 
247 	if (xe_bo_madv_is_dontneed(bo)) {
248 		ret = -EBUSY;
249 		goto out_unlock;
250 	}
251 
252 	if (xe_bo_is_purged(bo)) {
253 		ret = -EINVAL;
254 		goto out_unlock;
255 	}
256 
257 	xe_bo_willneed_get_locked(bo);
258 	xe_bo_unlock(bo);
259 
260 	ret = ttm_bo_setup_export(&bo->ttm, &ctx);
261 	if (ret)
262 		goto out_put;
263 
264 	buf = drm_gem_prime_export(obj, flags);
265 	if (IS_ERR(buf)) {
266 		ret = PTR_ERR(buf);
267 		goto out_put;
268 	}
269 
270 	buf->ops = &xe_dmabuf_ops;
271 	return buf;
272 
273 out_put:
274 	xe_bo_lock(bo, false);
275 	xe_bo_willneed_put_locked(bo);
276 out_unlock:
277 	xe_bo_unlock(bo);
278 	return ERR_PTR(ret);
279 }
280 
281 static struct drm_gem_object *
xe_dma_buf_create_obj(struct drm_device * dev,struct dma_buf * dma_buf)282 xe_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
283 {
284 	struct dma_resv *resv = dma_buf->resv;
285 	struct xe_device *xe = to_xe_device(dev);
286 	struct xe_validation_ctx ctx;
287 	struct drm_gem_object *dummy_obj;
288 	struct drm_exec exec;
289 	struct xe_bo *bo;
290 	int ret = 0;
291 
292 	dummy_obj = drm_gpuvm_resv_object_alloc(&xe->drm);
293 	if (!dummy_obj)
294 		return ERR_PTR(-ENOMEM);
295 
296 	dummy_obj->resv = resv;
297 	xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {}, ret) {
298 		ret = drm_exec_lock_obj(&exec, dummy_obj);
299 		drm_exec_retry_on_contention(&exec);
300 		if (ret)
301 			break;
302 
303 		bo = xe_bo_init_locked(xe, NULL, NULL, resv, NULL, dma_buf->size,
304 				       0, /* Will require 1way or 2way for vm_bind */
305 				       ttm_bo_type_sg, XE_BO_FLAG_SYSTEM, &exec);
306 		drm_exec_retry_on_contention(&exec);
307 		if (IS_ERR(bo)) {
308 			ret = PTR_ERR(bo);
309 			xe_validation_retry_on_oom(&ctx, &ret);
310 			break;
311 		}
312 	}
313 	drm_gem_object_put(dummy_obj);
314 
315 	return ret ? ERR_PTR(ret) : &bo->ttm.base;
316 }
317 
xe_dma_buf_move_notify(struct dma_buf_attachment * attach)318 static void xe_dma_buf_move_notify(struct dma_buf_attachment *attach)
319 {
320 	struct drm_gem_object *obj = attach->importer_priv;
321 	struct xe_bo *bo = gem_to_xe_bo(obj);
322 	struct drm_exec *exec = XE_VALIDATION_UNSUPPORTED;
323 
324 	XE_WARN_ON(xe_bo_evict(bo, exec));
325 }
326 
327 static const struct dma_buf_attach_ops xe_dma_buf_attach_ops = {
328 	.allow_peer2peer = true,
329 	.invalidate_mappings = xe_dma_buf_move_notify
330 };
331 
332 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
333 
334 struct dma_buf_test_params {
335 	struct xe_test_priv base;
336 	const struct dma_buf_attach_ops *attach_ops;
337 	bool force_different_devices;
338 	u32 mem_mask;
339 };
340 
341 #define to_dma_buf_test_params(_priv) \
342 	container_of(_priv, struct dma_buf_test_params, base)
343 #endif
344 
xe_gem_prime_import(struct drm_device * dev,struct dma_buf * dma_buf)345 struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev,
346 					   struct dma_buf *dma_buf)
347 {
348 	XE_TEST_DECLARE(struct dma_buf_test_params *test =
349 			to_dma_buf_test_params
350 			(xe_cur_kunit_priv(XE_TEST_LIVE_DMA_BUF));)
351 	const struct dma_buf_attach_ops *attach_ops;
352 	struct dma_buf_attachment *attach;
353 	struct drm_gem_object *obj;
354 
355 	if (dma_buf->ops == &xe_dmabuf_ops) {
356 		obj = dma_buf->priv;
357 		if (obj->dev == dev &&
358 		    !XE_TEST_ONLY(test && test->force_different_devices)) {
359 			/*
360 			 * Importing dmabuf exported from out own gem increases
361 			 * refcount on gem itself instead of f_count of dmabuf.
362 			 */
363 			drm_gem_object_get(obj);
364 			return obj;
365 		}
366 	}
367 
368 	/*
369 	 * This needs to happen before the attach, since it will create a new
370 	 * attachment for this, and add it to the list of attachments, at which
371 	 * point it is globally visible, and at any point the export side can
372 	 * call into on invalidate_mappings callback, which require a working
373 	 * object.
374 	 */
375 	obj = xe_dma_buf_create_obj(dev, dma_buf);
376 	if (IS_ERR(obj))
377 		return obj;
378 
379 	attach_ops = &xe_dma_buf_attach_ops;
380 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
381 	if (test)
382 		attach_ops = test->attach_ops;
383 #endif
384 
385 	attach = dma_buf_dynamic_attach(dma_buf, dev->dev, attach_ops, obj);
386 	if (IS_ERR(attach)) {
387 		xe_bo_put(gem_to_xe_bo(obj));
388 		return ERR_CAST(attach);
389 	}
390 
391 	get_dma_buf(dma_buf);
392 	obj->import_attach = attach;
393 	return obj;
394 }
395 
396 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
397 #include "tests/xe_dma_buf.c"
398 #endif
399