diff mbox series

[3/3] drm/amdgpu: Refuse non-P2P dma-buf attachments for BOs with KMS FBs

Message ID 20240222172821.16901-3-michel@daenzer.net (mailing list archive)
State New, archived
Headers show
Series [1/3] drm/amdgpu: Refuse to create a KMS FB for non-P2P exported dma-bufs | expand

Commit Message

Michel Dänzer Feb. 22, 2024, 5:28 p.m. UTC
From: Michel Dänzer <mdaenzer@redhat.com>

Pinning the BO storage to VRAM for scanout would make it inaccessible
to non-P2P dma-buf importers.

Also keep file_priv->prime.lock locked until after bumping bo->num_fbs
in amdgpu_display_user_framebuffer_create, so that the checks there and
in amdgpu_dma_buf_attach are always consistent with each other.

Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 20 ++++++++++++--------
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 11 +++++++++++
 2 files changed, 23 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 89bda2a2baf58..2afe5558ba895 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -1251,6 +1251,7 @@  amdgpu_display_user_framebuffer_create(struct drm_device *dev,
 {
 	struct amdgpu_framebuffer *amdgpu_fb;
 	struct drm_gem_object *obj;
+	bool prime_locked = false;
 	struct amdgpu_bo *bo;
 	uint32_t domains;
 	int ret;
@@ -1270,6 +1271,7 @@  amdgpu_display_user_framebuffer_create(struct drm_device *dev,
 		bool can_pin = true;
 
 		mutex_lock(&file_priv->prime.lock);
+		prime_locked = true;
 
 		/* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */
 		if (obj->import_attach) {
@@ -1293,29 +1295,31 @@  amdgpu_display_user_framebuffer_create(struct drm_device *dev,
 			dma_resv_unlock(dmabuf->resv);
 		}
 
-		mutex_unlock(&file_priv->prime.lock);
-
 		if (!can_pin) {
-			drm_gem_object_put(obj);
-			return ERR_PTR(-EINVAL);
+			amdgpu_fb = ERR_PTR(-EINVAL);
+			goto out;
 		}
 	}
 
 	amdgpu_fb = kzalloc(sizeof(*amdgpu_fb), GFP_KERNEL);
 	if (amdgpu_fb == NULL) {
-		drm_gem_object_put(obj);
-		return ERR_PTR(-ENOMEM);
+		amdgpu_fb = ERR_PTR(-ENOMEM);
+		goto out;
 	}
 
 	ret = amdgpu_display_gem_fb_verify_and_init(dev, amdgpu_fb, file_priv,
 						    mode_cmd, obj);
 	if (ret) {
 		kfree(amdgpu_fb);
-		drm_gem_object_put(obj);
-		return ERR_PTR(ret);
+		amdgpu_fb = ERR_PTR(ret);
+		goto out;
 	}
 
 	atomic_inc(&bo->num_fbs);
+
+out:
+	if (prime_locked)
+		mutex_unlock(&file_priv->prime.lock);
 	drm_gem_object_put(obj);
 	return &amdgpu_fb->base;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index decbbe3d4f06e..275d34898284d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -63,6 +63,17 @@  static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
 	if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
 		attach->peer2peer = false;
 
+	if ((!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY) || !attach->peer2peer) &&
+	    atomic_read(&bo->num_fbs) > 0) {
+		uint32_t domains = amdgpu_display_supported_domains(adev, bo->flags);
+
+		if (!(domains & AMDGPU_GEM_DOMAIN_GTT)) {
+			drm_dbg_prime(adev_to_drm(adev),
+				      "Cannot attach to BO with KMS FBs without P2P\n");
+			return -EINVAL;
+		}
+	}
+
 	r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
 	trace_amdgpu_runpm_reference_dumps(1, __func__);
 	if (r < 0)