0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include "amdgpu.h"
0035 #include "amdgpu_display.h"
0036 #include "amdgpu_gem.h"
0037 #include "amdgpu_dma_buf.h"
0038 #include "amdgpu_xgmi.h"
0039 #include <drm/amdgpu_drm.h>
0040 #include <linux/dma-buf.h>
0041 #include <linux/dma-fence-array.h>
0042 #include <linux/pci-p2pdma.h>
0043 #include <linux/pm_runtime.h>
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
0054 struct dma_buf_attachment *attach)
0055 {
0056 struct drm_gem_object *obj = dmabuf->priv;
0057 struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
0058 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
0059 int r;
0060
0061 if (pci_p2pdma_distance_many(adev->pdev, &attach->dev, 1, true) < 0)
0062 attach->peer2peer = false;
0063
0064 r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
0065 if (r < 0)
0066 goto out;
0067
0068 return 0;
0069
0070 out:
0071 pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
0072 return r;
0073 }
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
0084 struct dma_buf_attachment *attach)
0085 {
0086 struct drm_gem_object *obj = dmabuf->priv;
0087 struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
0088 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
0089
0090 pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
0091 pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101 static int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach)
0102 {
0103 struct drm_gem_object *obj = attach->dmabuf->priv;
0104 struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
0105
0106
0107 return amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
0108 }
0109
0110
0111
0112
0113
0114
0115
0116
0117 static void amdgpu_dma_buf_unpin(struct dma_buf_attachment *attach)
0118 {
0119 struct drm_gem_object *obj = attach->dmabuf->priv;
0120 struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
0121
0122 amdgpu_bo_unpin(bo);
0123 }
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
0139 enum dma_data_direction dir)
0140 {
0141 struct dma_buf *dma_buf = attach->dmabuf;
0142 struct drm_gem_object *obj = dma_buf->priv;
0143 struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
0144 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
0145 struct sg_table *sgt;
0146 long r;
0147
0148 if (!bo->tbo.pin_count) {
0149
0150 struct ttm_operation_ctx ctx = { false, false };
0151 unsigned domains = AMDGPU_GEM_DOMAIN_GTT;
0152
0153 if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM &&
0154 attach->peer2peer) {
0155 bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
0156 domains |= AMDGPU_GEM_DOMAIN_VRAM;
0157 }
0158 amdgpu_bo_placement_from_domain(bo, domains);
0159 r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
0160 if (r)
0161 return ERR_PTR(r);
0162
0163 } else if (!(amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type) &
0164 AMDGPU_GEM_DOMAIN_GTT)) {
0165 return ERR_PTR(-EBUSY);
0166 }
0167
0168 switch (bo->tbo.resource->mem_type) {
0169 case TTM_PL_TT:
0170 sgt = drm_prime_pages_to_sg(obj->dev,
0171 bo->tbo.ttm->pages,
0172 bo->tbo.ttm->num_pages);
0173 if (IS_ERR(sgt))
0174 return sgt;
0175
0176 if (dma_map_sgtable(attach->dev, sgt, dir,
0177 DMA_ATTR_SKIP_CPU_SYNC))
0178 goto error_free;
0179 break;
0180
0181 case TTM_PL_VRAM:
0182 r = amdgpu_vram_mgr_alloc_sgt(adev, bo->tbo.resource, 0,
0183 bo->tbo.base.size, attach->dev,
0184 dir, &sgt);
0185 if (r)
0186 return ERR_PTR(r);
0187 break;
0188 default:
0189 return ERR_PTR(-EINVAL);
0190 }
0191
0192 return sgt;
0193
0194 error_free:
0195 sg_free_table(sgt);
0196 kfree(sgt);
0197 return ERR_PTR(-EBUSY);
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209 static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
0210 struct sg_table *sgt,
0211 enum dma_data_direction dir)
0212 {
0213 if (sgt->sgl->page_link) {
0214 dma_unmap_sgtable(attach->dev, sgt, dir, 0);
0215 sg_free_table(sgt);
0216 kfree(sgt);
0217 } else {
0218 amdgpu_vram_mgr_free_sgt(attach->dev, dir, sgt);
0219 }
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
0235 enum dma_data_direction direction)
0236 {
0237 struct amdgpu_bo *bo = gem_to_amdgpu_bo(dma_buf->priv);
0238 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
0239 struct ttm_operation_ctx ctx = { true, false };
0240 u32 domain = amdgpu_display_supported_domains(adev, bo->flags);
0241 int ret;
0242 bool reads = (direction == DMA_BIDIRECTIONAL ||
0243 direction == DMA_FROM_DEVICE);
0244
0245 if (!reads || !(domain & AMDGPU_GEM_DOMAIN_GTT))
0246 return 0;
0247
0248
0249 ret = amdgpu_bo_reserve(bo, false);
0250 if (unlikely(ret != 0))
0251 return ret;
0252
0253 if (!bo->tbo.pin_count &&
0254 (bo->allowed_domains & AMDGPU_GEM_DOMAIN_GTT)) {
0255 amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
0256 ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
0257 }
0258
0259 amdgpu_bo_unreserve(bo);
0260 return ret;
0261 }
0262
0263 const struct dma_buf_ops amdgpu_dmabuf_ops = {
0264 .attach = amdgpu_dma_buf_attach,
0265 .detach = amdgpu_dma_buf_detach,
0266 .pin = amdgpu_dma_buf_pin,
0267 .unpin = amdgpu_dma_buf_unpin,
0268 .map_dma_buf = amdgpu_dma_buf_map,
0269 .unmap_dma_buf = amdgpu_dma_buf_unmap,
0270 .release = drm_gem_dmabuf_release,
0271 .begin_cpu_access = amdgpu_dma_buf_begin_cpu_access,
0272 .mmap = drm_gem_dmabuf_mmap,
0273 .vmap = drm_gem_dmabuf_vmap,
0274 .vunmap = drm_gem_dmabuf_vunmap,
0275 };
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
0288 int flags)
0289 {
0290 struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
0291 struct dma_buf *buf;
0292
0293 if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) ||
0294 bo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID)
0295 return ERR_PTR(-EPERM);
0296
0297 buf = drm_gem_prime_export(gobj, flags);
0298 if (!IS_ERR(buf))
0299 buf->ops = &amdgpu_dmabuf_ops;
0300
0301 return buf;
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 static struct drm_gem_object *
0317 amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
0318 {
0319 struct dma_resv *resv = dma_buf->resv;
0320 struct amdgpu_device *adev = drm_to_adev(dev);
0321 struct drm_gem_object *gobj;
0322 struct amdgpu_bo *bo;
0323 uint64_t flags = 0;
0324 int ret;
0325
0326 dma_resv_lock(resv, NULL);
0327
0328 if (dma_buf->ops == &amdgpu_dmabuf_ops) {
0329 struct amdgpu_bo *other = gem_to_amdgpu_bo(dma_buf->priv);
0330
0331 flags |= other->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC;
0332 }
0333
0334 ret = amdgpu_gem_object_create(adev, dma_buf->size, PAGE_SIZE,
0335 AMDGPU_GEM_DOMAIN_CPU, flags,
0336 ttm_bo_type_sg, resv, &gobj);
0337 if (ret)
0338 goto error;
0339
0340 bo = gem_to_amdgpu_bo(gobj);
0341 bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
0342 bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
0343
0344 dma_resv_unlock(resv);
0345 return gobj;
0346
0347 error:
0348 dma_resv_unlock(resv);
0349 return ERR_PTR(ret);
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360 static void
0361 amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach)
0362 {
0363 struct drm_gem_object *obj = attach->importer_priv;
0364 struct ww_acquire_ctx *ticket = dma_resv_locking_ctx(obj->resv);
0365 struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
0366 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
0367 struct ttm_operation_ctx ctx = { false, false };
0368 struct ttm_placement placement = {};
0369 struct amdgpu_vm_bo_base *bo_base;
0370 int r;
0371
0372 if (!bo->tbo.resource || bo->tbo.resource->mem_type == TTM_PL_SYSTEM)
0373 return;
0374
0375 r = ttm_bo_validate(&bo->tbo, &placement, &ctx);
0376 if (r) {
0377 DRM_ERROR("Failed to invalidate DMA-buf import (%d))\n", r);
0378 return;
0379 }
0380
0381 for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) {
0382 struct amdgpu_vm *vm = bo_base->vm;
0383 struct dma_resv *resv = vm->root.bo->tbo.base.resv;
0384
0385 if (ticket) {
0386
0387
0388
0389
0390 r = dma_resv_lock(resv, ticket);
0391 if (r)
0392 continue;
0393
0394 } else {
0395
0396
0397
0398
0399 if (!dma_resv_trylock(resv))
0400 continue;
0401 }
0402
0403 r = amdgpu_vm_clear_freed(adev, vm, NULL);
0404 if (!r)
0405 r = amdgpu_vm_handle_moved(adev, vm);
0406
0407 if (r && r != -EBUSY)
0408 DRM_ERROR("Failed to invalidate VM page tables (%d))\n",
0409 r);
0410
0411 dma_resv_unlock(resv);
0412 }
0413 }
0414
0415 static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops = {
0416 .allow_peer2peer = true,
0417 .move_notify = amdgpu_dma_buf_move_notify
0418 };
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430 struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
0431 struct dma_buf *dma_buf)
0432 {
0433 struct dma_buf_attachment *attach;
0434 struct drm_gem_object *obj;
0435
0436 if (dma_buf->ops == &amdgpu_dmabuf_ops) {
0437 obj = dma_buf->priv;
0438 if (obj->dev == dev) {
0439
0440
0441
0442
0443 drm_gem_object_get(obj);
0444 return obj;
0445 }
0446 }
0447
0448 obj = amdgpu_dma_buf_create_obj(dev, dma_buf);
0449 if (IS_ERR(obj))
0450 return obj;
0451
0452 attach = dma_buf_dynamic_attach(dma_buf, dev->dev,
0453 &amdgpu_dma_buf_attach_ops, obj);
0454 if (IS_ERR(attach)) {
0455 drm_gem_object_put(obj);
0456 return ERR_CAST(attach);
0457 }
0458
0459 get_dma_buf(dma_buf);
0460 obj->import_attach = attach;
0461 return obj;
0462 }
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473 bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev,
0474 struct amdgpu_bo *bo)
0475 {
0476 struct drm_gem_object *obj = &bo->tbo.base;
0477 struct drm_gem_object *gobj;
0478
0479 if (obj->import_attach) {
0480 struct dma_buf *dma_buf = obj->import_attach->dmabuf;
0481
0482 if (dma_buf->ops != &amdgpu_dmabuf_ops)
0483
0484 return false;
0485
0486 gobj = dma_buf->priv;
0487 bo = gem_to_amdgpu_bo(gobj);
0488 }
0489
0490 if (amdgpu_xgmi_same_hive(adev, amdgpu_ttm_adev(bo->tbo.bdev)) &&
0491 (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM))
0492 return true;
0493
0494 return false;
0495 }