All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Rob Clark <robdclark@chromium.org>,
	Daniel Vetter <daniel.vetter@ffwll.ch>,
	Sean Paul <seanpaul@chromium.org>,
	Sasha Levin <sashal@kernel.org>,
	dri-devel@lists.freedesktop.org
Subject: [PATCH AUTOSEL 4.14 17/25] drm/vgem: fix cache synchronization on arm/arm64
Date: Tue,  6 Aug 2019 17:36:14 -0400	[thread overview]
Message-ID: <20190806213624.20194-17-sashal@kernel.org> (raw)
In-Reply-To: <20190806213624.20194-1-sashal@kernel.org>

From: Rob Clark <robdclark@chromium.org>

[ Upstream commit 7e9e5ead55beacc11116b3fb90b0de6e7cf55a69 ]

drm_cflush_pages() is no-op on arm/arm64.  But instead we can use
dma_sync API.

Fixes failures w/ vgem_test.

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Rob Clark <robdclark@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190717211542.30482-1-robdclark@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/vgem/vgem_drv.c | 130 ++++++++++++++++++++------------
 1 file changed, 83 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
index aa592277d5108..b0aa362a31e41 100644
--- a/drivers/gpu/drm/vgem/vgem_drv.c
+++ b/drivers/gpu/drm/vgem/vgem_drv.c
@@ -47,10 +47,16 @@ static struct vgem_device {
 	struct platform_device *platform;
 } *vgem_device;
 
+static void sync_and_unpin(struct drm_vgem_gem_object *bo);
+static struct page **pin_and_sync(struct drm_vgem_gem_object *bo);
+
 static void vgem_gem_free_object(struct drm_gem_object *obj)
 {
 	struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj);
 
+	if (!obj->import_attach)
+		sync_and_unpin(vgem_obj);
+
 	kvfree(vgem_obj->pages);
 	mutex_destroy(&vgem_obj->pages_lock);
 
@@ -79,40 +85,15 @@ static int vgem_gem_fault(struct vm_fault *vmf)
 
 	ret = -ENOENT;
 	mutex_lock(&obj->pages_lock);
+	if (!obj->pages)
+		pin_and_sync(obj);
 	if (obj->pages) {
 		get_page(obj->pages[page_offset]);
 		vmf->page = obj->pages[page_offset];
 		ret = 0;
 	}
 	mutex_unlock(&obj->pages_lock);
-	if (ret) {
-		struct page *page;
-
-		page = shmem_read_mapping_page(
-					file_inode(obj->base.filp)->i_mapping,
-					page_offset);
-		if (!IS_ERR(page)) {
-			vmf->page = page;
-			ret = 0;
-		} else switch (PTR_ERR(page)) {
-			case -ENOSPC:
-			case -ENOMEM:
-				ret = VM_FAULT_OOM;
-				break;
-			case -EBUSY:
-				ret = VM_FAULT_RETRY;
-				break;
-			case -EFAULT:
-			case -EINVAL:
-				ret = VM_FAULT_SIGBUS;
-				break;
-			default:
-				WARN_ON(PTR_ERR(page));
-				ret = VM_FAULT_SIGBUS;
-				break;
-		}
 
-	}
 	return ret;
 }
 
@@ -278,32 +259,93 @@ static const struct file_operations vgem_driver_fops = {
 	.release	= drm_release,
 };
 
-static struct page **vgem_pin_pages(struct drm_vgem_gem_object *bo)
+/* Called under pages_lock, except in free path (where it can't race): */
+static void sync_and_unpin(struct drm_vgem_gem_object *bo)
 {
-	mutex_lock(&bo->pages_lock);
-	if (bo->pages_pin_count++ == 0) {
-		struct page **pages;
+	struct drm_device *dev = bo->base.dev;
+
+	if (bo->table) {
+		dma_sync_sg_for_cpu(dev->dev, bo->table->sgl,
+				bo->table->nents, DMA_BIDIRECTIONAL);
+		sg_free_table(bo->table);
+		kfree(bo->table);
+		bo->table = NULL;
+	}
+
+	if (bo->pages) {
+		drm_gem_put_pages(&bo->base, bo->pages, true, true);
+		bo->pages = NULL;
+	}
+}
+
+static struct page **pin_and_sync(struct drm_vgem_gem_object *bo)
+{
+	struct drm_device *dev = bo->base.dev;
+	int npages = bo->base.size >> PAGE_SHIFT;
+	struct page **pages;
+	struct sg_table *sgt;
+
+	WARN_ON(!mutex_is_locked(&bo->pages_lock));
+
+	pages = drm_gem_get_pages(&bo->base);
+	if (IS_ERR(pages)) {
+		bo->pages_pin_count--;
+		mutex_unlock(&bo->pages_lock);
+		return pages;
+	}
 
-		pages = drm_gem_get_pages(&bo->base);
-		if (IS_ERR(pages)) {
-			bo->pages_pin_count--;
-			mutex_unlock(&bo->pages_lock);
-			return pages;
-		}
+	sgt = drm_prime_pages_to_sg(pages, npages);
+	if (IS_ERR(sgt)) {
+		dev_err(dev->dev,
+			"failed to allocate sgt: %ld\n",
+			PTR_ERR(bo->table));
+		drm_gem_put_pages(&bo->base, pages, false, false);
+		mutex_unlock(&bo->pages_lock);
+		return ERR_CAST(bo->table);
+	}
+
+	/*
+	 * Flush the object from the CPU cache so that importers
+	 * can rely on coherent indirect access via the exported
+	 * dma-address.
+	 */
+	dma_sync_sg_for_device(dev->dev, sgt->sgl,
+			sgt->nents, DMA_BIDIRECTIONAL);
+
+	bo->pages = pages;
+	bo->table = sgt;
+
+	return pages;
+}
+
+static struct page **vgem_pin_pages(struct drm_vgem_gem_object *bo)
+{
+	struct page **pages;
 
-		bo->pages = pages;
+	mutex_lock(&bo->pages_lock);
+	if (bo->pages_pin_count++ == 0 && !bo->pages) {
+		pages = pin_and_sync(bo);
+	} else {
+		WARN_ON(!bo->pages);
+		pages = bo->pages;
 	}
 	mutex_unlock(&bo->pages_lock);
 
-	return bo->pages;
+	return pages;
 }
 
 static void vgem_unpin_pages(struct drm_vgem_gem_object *bo)
 {
+	/*
+	 * We shouldn't hit this for imported bo's.. in the import
+	 * case we don't own the scatter-table
+	 */
+	WARN_ON(bo->base.import_attach);
+
 	mutex_lock(&bo->pages_lock);
 	if (--bo->pages_pin_count == 0) {
-		drm_gem_put_pages(&bo->base, bo->pages, true, true);
-		bo->pages = NULL;
+		WARN_ON(!bo->table);
+		sync_and_unpin(bo);
 	}
 	mutex_unlock(&bo->pages_lock);
 }
@@ -311,18 +353,12 @@ static void vgem_unpin_pages(struct drm_vgem_gem_object *bo)
 static int vgem_prime_pin(struct drm_gem_object *obj)
 {
 	struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
-	long n_pages = obj->size >> PAGE_SHIFT;
 	struct page **pages;
 
 	pages = vgem_pin_pages(bo);
 	if (IS_ERR(pages))
 		return PTR_ERR(pages);
 
-	/* Flush the object from the CPU cache so that importers can rely
-	 * on coherent indirect access via the exported dma-address.
-	 */
-	drm_clflush_pages(pages, n_pages);
-
 	return 0;
 }
 
-- 
2.20.1

  parent reply	other threads:[~2019-08-06 21:36 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-06 21:35 [PATCH AUTOSEL 4.14 01/25] clk: at91: generated: Truncate divisor to GENERATED_MAX_DIV + 1 Sasha Levin
2019-08-06 21:35 ` [PATCH AUTOSEL 4.14 02/25] clk: renesas: cpg-mssr: Fix reset control race condition Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 03/25] xtensa: fix build for cores with coprocessors Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 04/25] xen/pciback: remove set but not used variable 'old_state' Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 05/25] irqchip/gic-v3-its: Free unused vpt_page when alloc vpe table fail Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 06/25] irqchip/irq-imx-gpcv2: Forward irq type to parent Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 07/25] perf header: Fix divide by zero error if f_header.attr_size==0 Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 08/25] perf header: Fix use of unitialized value warning Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 09/25] libata: zpodd: Fix small read overflow in zpodd_get_mech_type() Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 10/25] drm/bridge: lvds-encoder: Fix build error while CONFIG_DRM_KMS_HELPER=m Sasha Levin
2019-08-06 21:36   ` Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 11/25] scsi: hpsa: correct scsi command status issue after reset Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 12/25] scsi: qla2xxx: Fix possible fcport null-pointer dereferences Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 13/25] exit: make setting exit_state consistent Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 14/25] ata: libahci: do not complain in case of deferred probe Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 15/25] kbuild: modpost: handle KBUILD_EXTRA_SYMBOLS only for external modules Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 16/25] arm64/efi: fix variable 'si' set but not used Sasha Levin
2019-08-06 21:36 ` Sasha Levin [this message]
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 18/25] arm64: unwind: Prohibit probing on return_address() Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 19/25] arm64/mm: fix variable 'pud' set but not used Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 20/25] IB/core: Add mitigation for Spectre V1 Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 21/25] IB/mad: Fix use-after-free in ib mad completion handling Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 22/25] drm: msm: Fix add_gpu_components Sasha Levin
2019-08-06 21:36   ` Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 23/25] ocfs2: remove set but not used variable 'last_hash' Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 24/25] coredump: split pipe command whitespace before expanding template Sasha Levin
2019-08-06 21:36 ` [PATCH AUTOSEL 4.14 25/25] asm-generic: fix -Wtype-limits compiler warnings Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190806213624.20194-17-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=daniel.vetter@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robdclark@chromium.org \
    --cc=seanpaul@chromium.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.