All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] drm/msm: fencification
@ 2016-03-18 23:14 Rob Clark
  2016-03-18 23:14 ` [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked() Rob Clark
                   ` (10 more replies)
  0 siblings, 11 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:14 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, maarten.lankhorst, linux-arm-msm, freedreno, Rob Clark

A few prep patches, plus drm/msm conversion to 'struct fence' for gpu
and display sync.  Uses drm_atomic_helper_wait_for_fences() to sync
atomic updates with rendering.

This is the first step towards implementing EGL_ANDROID_native_fence_sync.
Next step would be to extend submit uapi to use syncpt fd's (and then
eventually somehow plumb through atomic ioctl for fully explicit sync).

Rob Clark (11):
  reservation: add reservation_object_get_excl_unlocked()
  drm/atomic: export drm_atomic_helper_wait_for_fences()
  drm/msm: move debugfs code to it's own file
  drm/msm: move fence code to it's own file
  drm/msm: use imported dmabuf's reservation object
  drm/msm: split out timeout_to_jiffies helper
  drm/msm/gpu: simplify tracking in-flight bo's
  drm/msm: split locking and pinning BO's
  drm/msm: introduce msm_fence_context
  drm/msm: remove fence_cbs
  drm/msm: 'struct fence' conversion

 drivers/gpu/drm/drm_atomic_helper.c     |  15 +-
 drivers/gpu/drm/msm/Makefile            |   2 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.c |  10 +-
 drivers/gpu/drm/msm/msm_atomic.c        |  47 +++---
 drivers/gpu/drm/msm/msm_debugfs.c       | 168 ++++++++++++++++++++
 drivers/gpu/drm/msm/msm_debugfs.h       |  26 +++
 drivers/gpu/drm/msm/msm_drv.c           | 273 ++------------------------------
 drivers/gpu/drm/msm/msm_drv.h           |  59 +++----
 drivers/gpu/drm/msm/msm_fence.c         | 163 +++++++++++++++++++
 drivers/gpu/drm/msm/msm_fence.h         |  46 ++++++
 drivers/gpu/drm/msm/msm_gem.c           | 132 ++++++++++++---
 drivers/gpu/drm/msm/msm_gem.h           |  18 +--
 drivers/gpu/drm/msm/msm_gem_prime.c     |   2 +-
 drivers/gpu/drm/msm/msm_gem_submit.c    |  91 +++++++----
 drivers/gpu/drm/msm/msm_gpu.c           | 100 ++++++------
 drivers/gpu/drm/msm/msm_gpu.h           |   7 +-
 drivers/gpu/drm/msm/msm_rd.c            |   2 +-
 include/drm/drm_atomic_helper.h         |   2 +
 include/linux/reservation.h             |  18 +++
 19 files changed, 724 insertions(+), 457 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/msm_debugfs.c
 create mode 100644 drivers/gpu/drm/msm/msm_debugfs.h
 create mode 100644 drivers/gpu/drm/msm/msm_fence.c
 create mode 100644 drivers/gpu/drm/msm/msm_fence.h

-- 
2.5.0

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked()
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
@ 2016-03-18 23:14 ` Rob Clark
  2016-03-31 20:23   ` Rob Clark
  2016-03-18 23:14 ` [PATCH 02/11] drm/atomic: export drm_atomic_helper_wait_for_fences() Rob Clark
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:14 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, maarten.lankhorst, linux-arm-msm, freedreno, Rob Clark

In the atomic modesetting path, each driver simply wants to grab a ref
to the exlusive fence from a reservation object to store in the incoming
drm_plane_state, without doing the whole RCU dance.  Since each driver
will need to do this, lets make a helper.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 include/linux/reservation.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index 5a0b64c..7a018a9 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -120,6 +120,24 @@ reservation_object_get_excl(struct reservation_object *obj)
 					 reservation_object_held(obj));
 }
 
+static inline struct fence *
+reservation_object_get_excl_unlocked(struct reservation_object *obj)
+{
+	struct fence *fence;
+	unsigned seq;
+retry:
+	seq = read_seqcount_begin(&obj->seq);
+	rcu_read_lock();
+	fence = rcu_dereference(obj->fence_excl);
+	if (read_seqcount_retry(&obj->seq, seq)) {
+		rcu_read_unlock();
+		goto retry;
+	}
+	fence = fence_get(fence);
+	rcu_read_unlock();
+	return fence;
+}
+
 int reservation_object_reserve_shared(struct reservation_object *obj);
 void reservation_object_add_shared_fence(struct reservation_object *obj,
 					 struct fence *fence);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 02/11] drm/atomic: export drm_atomic_helper_wait_for_fences()
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
  2016-03-18 23:14 ` [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked() Rob Clark
@ 2016-03-18 23:14 ` Rob Clark
  2016-03-30 20:51   ` Gustavo Padovan
  2016-03-18 23:14 ` [PATCH 03/11] drm/msm: move debugfs code to it's own file Rob Clark
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:14 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, maarten.lankhorst, linux-arm-msm, freedreno, Rob Clark

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 15 +++++++++++++--
 include/drm/drm_atomic_helper.h     |  2 ++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 7c52306..aa72732 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -927,7 +927,17 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
 
-static void wait_for_fences(struct drm_device *dev,
+/**
+ * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state
+ * @dev: DRM device
+ * @state: atomic state object with old state structures
+ *
+ * For implicit sync, driver should fish the exclusive fence out from the
+ * incoming fb's and stash it in the drm_plane_state.  This is called after
+ * drm_atomic_helper_swap_state() so it uses the current plane state (and
+ * just uses the atomic state to find the changed planes)
+ */
+void drm_atomic_helper_wait_for_fences(struct drm_device *dev,
 			    struct drm_atomic_state *state)
 {
 	struct drm_plane *plane;
@@ -945,6 +955,7 @@ static void wait_for_fences(struct drm_device *dev,
 		plane->state->fence = NULL;
 	}
 }
+EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences);
 
 /**
  * drm_atomic_helper_framebuffer_changed - check if framebuffer has changed
@@ -1106,7 +1117,7 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 	 * current layout.
 	 */
 
-	wait_for_fences(dev, state);
+	drm_atomic_helper_wait_for_fences(dev, state);
 
 	drm_atomic_helper_commit_modeset_disables(dev, state);
 
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index fe5efad..2b20b28 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -42,6 +42,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 			     struct drm_atomic_state *state,
 			     bool async);
 
+void drm_atomic_helper_wait_for_fences(struct drm_device *dev,
+					struct drm_atomic_state *state);
 bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev,
 					   struct drm_atomic_state *old_state,
 					   struct drm_crtc *crtc);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 03/11] drm/msm: move debugfs code to it's own file
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
  2016-03-18 23:14 ` [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked() Rob Clark
  2016-03-18 23:14 ` [PATCH 02/11] drm/atomic: export drm_atomic_helper_wait_for_fences() Rob Clark
@ 2016-03-18 23:14 ` Rob Clark
  2016-03-18 23:14 ` [PATCH 04/11] drm/msm: move fence " Rob Clark
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:14 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, maarten.lankhorst, linux-arm-msm, freedreno, Rob Clark

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/Makefile      |   1 +
 drivers/gpu/drm/msm/msm_debugfs.c | 168 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_debugfs.h |  26 ++++++
 drivers/gpu/drm/msm/msm_drv.c     | 153 +---------------------------------
 4 files changed, 196 insertions(+), 152 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/msm_debugfs.c
 create mode 100644 drivers/gpu/drm/msm/msm_debugfs.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 9386cfe..cfec4bb 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -23,6 +23,7 @@ msm-y := \
 	mdp/mdp5/mdp5_plane.o \
 	mdp/mdp5/mdp5_smp.o \
 	msm_atomic.o \
+	msm_debugfs.o \
 	msm_drv.o \
 	msm_fb.o \
 	msm_gem.o \
diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c
new file mode 100644
index 0000000..663f2b6
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_debugfs.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef CONFIG_DEBUG_FS
+#include "msm_drv.h"
+#include "msm_gpu.h"
+
+static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	struct msm_gpu *gpu = priv->gpu;
+
+	if (gpu) {
+		seq_printf(m, "%s Status:\n", gpu->name);
+		gpu->funcs->show(gpu, m);
+	}
+
+	return 0;
+}
+
+static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	struct msm_gpu *gpu = priv->gpu;
+
+	if (gpu) {
+		seq_printf(m, "Active Objects (%s):\n", gpu->name);
+		msm_gem_describe_objects(&gpu->active_list, m);
+	}
+
+	seq_printf(m, "Inactive Objects:\n");
+	msm_gem_describe_objects(&priv->inactive_list, m);
+
+	return 0;
+}
+
+static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
+{
+	return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
+}
+
+static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	struct drm_framebuffer *fb, *fbdev_fb = NULL;
+
+	if (priv->fbdev) {
+		seq_printf(m, "fbcon ");
+		fbdev_fb = priv->fbdev->fb;
+		msm_framebuffer_describe(fbdev_fb, m);
+	}
+
+	mutex_lock(&dev->mode_config.fb_lock);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		if (fb == fbdev_fb)
+			continue;
+
+		seq_printf(m, "user ");
+		msm_framebuffer_describe(fb, m);
+	}
+	mutex_unlock(&dev->mode_config.fb_lock);
+
+	return 0;
+}
+
+static int show_locked(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	int (*show)(struct drm_device *dev, struct seq_file *m) =
+			node->info_ent->data;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	ret = show(dev, m);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static struct drm_info_list msm_debugfs_list[] = {
+		{"gpu", show_locked, 0, msm_gpu_show},
+		{"gem", show_locked, 0, msm_gem_show},
+		{ "mm", show_locked, 0, msm_mm_show },
+		{ "fb", show_locked, 0, msm_fb_show },
+};
+
+static int late_init_minor(struct drm_minor *minor)
+{
+	int ret;
+
+	if (!minor)
+		return 0;
+
+	ret = msm_rd_debugfs_init(minor);
+	if (ret) {
+		dev_err(minor->dev->dev, "could not install rd debugfs\n");
+		return ret;
+	}
+
+	ret = msm_perf_debugfs_init(minor);
+	if (ret) {
+		dev_err(minor->dev->dev, "could not install perf debugfs\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int msm_debugfs_late_init(struct drm_device *dev)
+{
+	int ret;
+	ret = late_init_minor(dev->primary);
+	if (ret)
+		return ret;
+	ret = late_init_minor(dev->render);
+	if (ret)
+		return ret;
+	ret = late_init_minor(dev->control);
+	return ret;
+}
+
+int msm_debugfs_init(struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	int ret;
+
+	ret = drm_debugfs_create_files(msm_debugfs_list,
+			ARRAY_SIZE(msm_debugfs_list),
+			minor->debugfs_root, minor);
+
+	if (ret) {
+		dev_err(dev->dev, "could not install msm_debugfs_list\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+void msm_debugfs_cleanup(struct drm_minor *minor)
+{
+	drm_debugfs_remove_files(msm_debugfs_list,
+			ARRAY_SIZE(msm_debugfs_list), minor);
+	if (!minor->dev->dev_private)
+		return;
+	msm_rd_debugfs_cleanup(minor);
+	msm_perf_debugfs_cleanup(minor);
+}
+#endif
+
diff --git a/drivers/gpu/drm/msm/msm_debugfs.h b/drivers/gpu/drm/msm/msm_debugfs.h
new file mode 100644
index 0000000..6110c97
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_debugfs.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MSM_DEBUGFS_H__
+#define __MSM_DEBUGFS_H__
+
+#ifdef CONFIG_DEBUG_FS
+int msm_debugfs_init(struct drm_minor *minor);
+void msm_debugfs_cleanup(struct drm_minor *minor);
+#endif
+
+#endif /* __MSM_DEBUGFS_H__ */
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 273e780..5e08ea9 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -16,6 +16,7 @@
  */
 
 #include "msm_drv.h"
+#include "msm_debugfs.h"
 #include "msm_gpu.h"
 #include "msm_kms.h"
 
@@ -539,158 +540,6 @@ static void msm_disable_vblank(struct drm_device *dev, unsigned int pipe)
 }
 
 /*
- * DRM debugfs:
- */
-
-#ifdef CONFIG_DEBUG_FS
-static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_gpu *gpu = priv->gpu;
-
-	if (gpu) {
-		seq_printf(m, "%s Status:\n", gpu->name);
-		gpu->funcs->show(gpu, m);
-	}
-
-	return 0;
-}
-
-static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_gpu *gpu = priv->gpu;
-
-	if (gpu) {
-		seq_printf(m, "Active Objects (%s):\n", gpu->name);
-		msm_gem_describe_objects(&gpu->active_list, m);
-	}
-
-	seq_printf(m, "Inactive Objects:\n");
-	msm_gem_describe_objects(&priv->inactive_list, m);
-
-	return 0;
-}
-
-static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
-{
-	return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
-}
-
-static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	struct drm_framebuffer *fb, *fbdev_fb = NULL;
-
-	if (priv->fbdev) {
-		seq_printf(m, "fbcon ");
-		fbdev_fb = priv->fbdev->fb;
-		msm_framebuffer_describe(fbdev_fb, m);
-	}
-
-	mutex_lock(&dev->mode_config.fb_lock);
-	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-		if (fb == fbdev_fb)
-			continue;
-
-		seq_printf(m, "user ");
-		msm_framebuffer_describe(fb, m);
-	}
-	mutex_unlock(&dev->mode_config.fb_lock);
-
-	return 0;
-}
-
-static int show_locked(struct seq_file *m, void *arg)
-{
-	struct drm_info_node *node = (struct drm_info_node *) m->private;
-	struct drm_device *dev = node->minor->dev;
-	int (*show)(struct drm_device *dev, struct seq_file *m) =
-			node->info_ent->data;
-	int ret;
-
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-
-	ret = show(dev, m);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
-static struct drm_info_list msm_debugfs_list[] = {
-		{"gpu", show_locked, 0, msm_gpu_show},
-		{"gem", show_locked, 0, msm_gem_show},
-		{ "mm", show_locked, 0, msm_mm_show },
-		{ "fb", show_locked, 0, msm_fb_show },
-};
-
-static int late_init_minor(struct drm_minor *minor)
-{
-	int ret;
-
-	if (!minor)
-		return 0;
-
-	ret = msm_rd_debugfs_init(minor);
-	if (ret) {
-		dev_err(minor->dev->dev, "could not install rd debugfs\n");
-		return ret;
-	}
-
-	ret = msm_perf_debugfs_init(minor);
-	if (ret) {
-		dev_err(minor->dev->dev, "could not install perf debugfs\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-int msm_debugfs_late_init(struct drm_device *dev)
-{
-	int ret;
-	ret = late_init_minor(dev->primary);
-	if (ret)
-		return ret;
-	ret = late_init_minor(dev->render);
-	if (ret)
-		return ret;
-	ret = late_init_minor(dev->control);
-	return ret;
-}
-
-static int msm_debugfs_init(struct drm_minor *minor)
-{
-	struct drm_device *dev = minor->dev;
-	int ret;
-
-	ret = drm_debugfs_create_files(msm_debugfs_list,
-			ARRAY_SIZE(msm_debugfs_list),
-			minor->debugfs_root, minor);
-
-	if (ret) {
-		dev_err(dev->dev, "could not install msm_debugfs_list\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static void msm_debugfs_cleanup(struct drm_minor *minor)
-{
-	drm_debugfs_remove_files(msm_debugfs_list,
-			ARRAY_SIZE(msm_debugfs_list), minor);
-	if (!minor->dev->dev_private)
-		return;
-	msm_rd_debugfs_cleanup(minor);
-	msm_perf_debugfs_cleanup(minor);
-}
-#endif
-
-/*
  * Fences:
  */
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 04/11] drm/msm: move fence code to it's own file
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (2 preceding siblings ...)
  2016-03-18 23:14 ` [PATCH 03/11] drm/msm: move debugfs code to it's own file Rob Clark
@ 2016-03-18 23:14 ` Rob Clark
  2016-03-18 23:14 ` [PATCH 05/11] drm/msm: use imported dmabuf's reservation object Rob Clark
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:14 UTC (permalink / raw)
  To: dri-devel; +Cc: maarten.lankhorst, linux-arm-msm, freedreno

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/Makefile     |   1 +
 drivers/gpu/drm/msm/msm_atomic.c |   1 +
 drivers/gpu/drm/msm/msm_drv.c    | 108 +-------------------------------
 drivers/gpu/drm/msm/msm_drv.h    |  27 +-------
 drivers/gpu/drm/msm/msm_fence.c  | 129 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_fence.h  |  43 +++++++++++++
 drivers/gpu/drm/msm/msm_gem.c    |   1 +
 drivers/gpu/drm/msm/msm_gpu.c    |   1 +
 8 files changed, 178 insertions(+), 133 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/msm_fence.c
 create mode 100644 drivers/gpu/drm/msm/msm_fence.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index cfec4bb..d2d9de8 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -26,6 +26,7 @@ msm-y := \
 	msm_debugfs.o \
 	msm_drv.o \
 	msm_fb.o \
+	msm_fence.o \
 	msm_gem.o \
 	msm_gem_prime.o \
 	msm_gem_submit.o \
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 7eb253b..3c0f7a8 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -18,6 +18,7 @@
 #include "msm_drv.h"
 #include "msm_kms.h"
 #include "msm_gem.h"
+#include "msm_fence.h"
 
 struct msm_commit {
 	struct drm_device *dev;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 5e08ea9..6988285 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -17,6 +17,7 @@
 
 #include "msm_drv.h"
 #include "msm_debugfs.h"
+#include "msm_fence.h"
 #include "msm_gpu.h"
 #include "msm_kms.h"
 
@@ -540,113 +541,6 @@ static void msm_disable_vblank(struct drm_device *dev, unsigned int pipe)
 }
 
 /*
- * Fences:
- */
-
-int msm_wait_fence(struct drm_device *dev, uint32_t fence,
-		ktime_t *timeout , bool interruptible)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	int ret;
-
-	if (!priv->gpu)
-		return 0;
-
-	if (fence > priv->gpu->submitted_fence) {
-		DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
-				fence, priv->gpu->submitted_fence);
-		return -EINVAL;
-	}
-
-	if (!timeout) {
-		/* no-wait: */
-		ret = fence_completed(dev, fence) ? 0 : -EBUSY;
-	} else {
-		ktime_t now = ktime_get();
-		unsigned long remaining_jiffies;
-
-		if (ktime_compare(*timeout, now) < 0) {
-			remaining_jiffies = 0;
-		} else {
-			ktime_t rem = ktime_sub(*timeout, now);
-			struct timespec ts = ktime_to_timespec(rem);
-			remaining_jiffies = timespec_to_jiffies(&ts);
-		}
-
-		if (interruptible)
-			ret = wait_event_interruptible_timeout(priv->fence_event,
-				fence_completed(dev, fence),
-				remaining_jiffies);
-		else
-			ret = wait_event_timeout(priv->fence_event,
-				fence_completed(dev, fence),
-				remaining_jiffies);
-
-		if (ret == 0) {
-			DBG("timeout waiting for fence: %u (completed: %u)",
-					fence, priv->completed_fence);
-			ret = -ETIMEDOUT;
-		} else if (ret != -ERESTARTSYS) {
-			ret = 0;
-		}
-	}
-
-	return ret;
-}
-
-int msm_queue_fence_cb(struct drm_device *dev,
-		struct msm_fence_cb *cb, uint32_t fence)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	int ret = 0;
-
-	mutex_lock(&dev->struct_mutex);
-	if (!list_empty(&cb->work.entry)) {
-		ret = -EINVAL;
-	} else if (fence > priv->completed_fence) {
-		cb->fence = fence;
-		list_add_tail(&cb->work.entry, &priv->fence_cbs);
-	} else {
-		queue_work(priv->wq, &cb->work);
-	}
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
-/* called from workqueue */
-void msm_update_fence(struct drm_device *dev, uint32_t fence)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-
-	mutex_lock(&dev->struct_mutex);
-	priv->completed_fence = max(fence, priv->completed_fence);
-
-	while (!list_empty(&priv->fence_cbs)) {
-		struct msm_fence_cb *cb;
-
-		cb = list_first_entry(&priv->fence_cbs,
-				struct msm_fence_cb, work.entry);
-
-		if (cb->fence > priv->completed_fence)
-			break;
-
-		list_del_init(&cb->work.entry);
-		queue_work(priv->wq, &cb->work);
-	}
-
-	mutex_unlock(&dev->struct_mutex);
-
-	wake_up_all(&priv->fence_event);
-}
-
-void __msm_fence_worker(struct work_struct *work)
-{
-	struct msm_fence_cb *cb = container_of(work, struct msm_fence_cb, work);
-	cb->func(cb);
-}
-
-/*
  * DRM ioctls:
  */
 
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6980aa4..dfd8c8b 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -49,6 +49,7 @@ struct msm_mmu;
 struct msm_rd_state;
 struct msm_perf_state;
 struct msm_gem_submit;
+struct msm_fence_cb;
 
 #define NUM_DOMAINS 2    /* one for KMS, then one per gpu core (?) */
 
@@ -157,20 +158,6 @@ struct msm_format {
 	uint32_t pixel_format;
 };
 
-/* callback from wq once fence has passed: */
-struct msm_fence_cb {
-	struct work_struct work;
-	uint32_t fence;
-	void (*func)(struct msm_fence_cb *cb);
-};
-
-void __msm_fence_worker(struct work_struct *work);
-
-#define INIT_FENCE_CB(_cb, _func)  do {                     \
-		INIT_WORK(&(_cb)->work, __msm_fence_worker); \
-		(_cb)->func = _func;                         \
-	} while (0)
-
 int msm_atomic_check(struct drm_device *dev,
 		     struct drm_atomic_state *state);
 int msm_atomic_commit(struct drm_device *dev,
@@ -178,12 +165,6 @@ int msm_atomic_commit(struct drm_device *dev,
 
 int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
 
-int msm_wait_fence(struct drm_device *dev, uint32_t fence,
-		ktime_t *timeout, bool interruptible);
-int msm_queue_fence_cb(struct drm_device *dev,
-		struct msm_fence_cb *cb, uint32_t fence);
-void msm_update_fence(struct drm_device *dev, uint32_t fence);
-
 int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 		struct drm_file *file);
 
@@ -336,12 +317,6 @@ u32 msm_readl(const void __iomem *addr);
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 
-static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	return priv->completed_fence >= fence;
-}
-
 static inline int align_pitch(int width, int bpp)
 {
 	int bytespp = (bpp + 7) / 8;
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
new file mode 100644
index 0000000..55a5f92
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "msm_drv.h"
+#include "msm_fence.h"
+#include "msm_gpu.h"
+
+static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	return (int32_t)(priv->completed_fence - fence) >= 0;
+}
+
+int msm_wait_fence(struct drm_device *dev, uint32_t fence,
+		ktime_t *timeout , bool interruptible)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	int ret;
+
+	if (!priv->gpu)
+		return 0;
+
+	if (fence > priv->gpu->submitted_fence) {
+		DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
+				fence, priv->gpu->submitted_fence);
+		return -EINVAL;
+	}
+
+	if (!timeout) {
+		/* no-wait: */
+		ret = fence_completed(dev, fence) ? 0 : -EBUSY;
+	} else {
+		ktime_t now = ktime_get();
+		unsigned long remaining_jiffies;
+
+		if (ktime_compare(*timeout, now) < 0) {
+			remaining_jiffies = 0;
+		} else {
+			ktime_t rem = ktime_sub(*timeout, now);
+			struct timespec ts = ktime_to_timespec(rem);
+			remaining_jiffies = timespec_to_jiffies(&ts);
+		}
+
+		if (interruptible)
+			ret = wait_event_interruptible_timeout(priv->fence_event,
+				fence_completed(dev, fence),
+				remaining_jiffies);
+		else
+			ret = wait_event_timeout(priv->fence_event,
+				fence_completed(dev, fence),
+				remaining_jiffies);
+
+		if (ret == 0) {
+			DBG("timeout waiting for fence: %u (completed: %u)",
+					fence, priv->completed_fence);
+			ret = -ETIMEDOUT;
+		} else if (ret != -ERESTARTSYS) {
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
+int msm_queue_fence_cb(struct drm_device *dev,
+		struct msm_fence_cb *cb, uint32_t fence)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	int ret = 0;
+
+	mutex_lock(&dev->struct_mutex);
+	if (!list_empty(&cb->work.entry)) {
+		ret = -EINVAL;
+	} else if (fence > priv->completed_fence) {
+		cb->fence = fence;
+		list_add_tail(&cb->work.entry, &priv->fence_cbs);
+	} else {
+		queue_work(priv->wq, &cb->work);
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+/* called from workqueue */
+void msm_update_fence(struct drm_device *dev, uint32_t fence)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+
+	mutex_lock(&dev->struct_mutex);
+	priv->completed_fence = max(fence, priv->completed_fence);
+
+	while (!list_empty(&priv->fence_cbs)) {
+		struct msm_fence_cb *cb;
+
+		cb = list_first_entry(&priv->fence_cbs,
+				struct msm_fence_cb, work.entry);
+
+		if (cb->fence > priv->completed_fence)
+			break;
+
+		list_del_init(&cb->work.entry);
+		queue_work(priv->wq, &cb->work);
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+	wake_up_all(&priv->fence_event);
+}
+
+void __msm_fence_worker(struct work_struct *work)
+{
+	struct msm_fence_cb *cb = container_of(work, struct msm_fence_cb, work);
+	cb->func(cb);
+}
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
new file mode 100644
index 0000000..6ddb81c
--- /dev/null
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MSM_FENCE_H__
+#define __MSM_FENCE_H__
+
+#include "msm_drv.h"
+
+/* callback from wq once fence has passed: */
+struct msm_fence_cb {
+	struct work_struct work;
+	uint32_t fence;
+	void (*func)(struct msm_fence_cb *cb);
+};
+
+void __msm_fence_worker(struct work_struct *work);
+
+#define INIT_FENCE_CB(_cb, _func)  do {                     \
+		INIT_WORK(&(_cb)->work, __msm_fence_worker); \
+		(_cb)->func = _func;                         \
+	} while (0)
+
+int msm_wait_fence(struct drm_device *dev, uint32_t fence,
+		ktime_t *timeout, bool interruptible);
+int msm_queue_fence_cb(struct drm_device *dev,
+		struct msm_fence_cb *cb, uint32_t fence);
+void msm_update_fence(struct drm_device *dev, uint32_t fence);
+
+#endif
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 3cedb8d..ef03ee7 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -21,6 +21,7 @@
 #include <linux/pfn_t.h>
 
 #include "msm_drv.h"
+#include "msm_fence.h"
 #include "msm_gem.h"
 #include "msm_gpu.h"
 #include "msm_mmu.h"
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 42e2284..5f6704c 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -18,6 +18,7 @@
 #include "msm_gpu.h"
 #include "msm_gem.h"
 #include "msm_mmu.h"
+#include "msm_fence.h"
 
 
 /*
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 05/11] drm/msm: use imported dmabuf's reservation object
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (3 preceding siblings ...)
  2016-03-18 23:14 ` [PATCH 04/11] drm/msm: move fence " Rob Clark
@ 2016-03-18 23:14 ` Rob Clark
  2016-03-18 23:14 ` [PATCH 06/11] drm/msm: split out timeout_to_jiffies helper Rob Clark
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:14 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, maarten.lankhorst, linux-arm-msm, freedreno, Rob Clark

This was always the intention, but somehow it was never wired up
properly.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/msm_drv.h       |  2 +-
 drivers/gpu/drm/msm/msm_gem.c       | 18 ++++++++++++------
 drivers/gpu/drm/msm/msm_gem_prime.c |  2 +-
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index dfd8c8b..fed3869 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -208,7 +208,7 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
 struct drm_gem_object *msm_gem_new(struct drm_device *dev,
 		uint32_t size, uint32_t flags);
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
-		uint32_t size, struct sg_table *sgt);
+		struct dma_buf *dmabuf, struct sg_table *sgt);
 
 int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id);
 void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index ef03ee7..09e2190 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -584,6 +584,7 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
 
 static int msm_gem_new_impl(struct drm_device *dev,
 		uint32_t size, uint32_t flags,
+		struct reservation_object *resv,
 		struct drm_gem_object **obj)
 {
 	struct msm_drm_private *priv = dev->dev_private;
@@ -623,8 +624,12 @@ static int msm_gem_new_impl(struct drm_device *dev,
 
 	msm_obj->flags = flags;
 
-	msm_obj->resv = &msm_obj->_resv;
-	reservation_object_init(msm_obj->resv);
+	if (resv) {
+		msm_obj->resv = resv;
+	} else {
+		msm_obj->resv = &msm_obj->_resv;
+		reservation_object_init(msm_obj->resv);
+	}
 
 	INIT_LIST_HEAD(&msm_obj->submit_entry);
 	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
@@ -644,7 +649,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,
 
 	size = PAGE_ALIGN(size);
 
-	ret = msm_gem_new_impl(dev, size, flags, &obj);
+	ret = msm_gem_new_impl(dev, size, flags, NULL, &obj);
 	if (ret)
 		goto fail;
 
@@ -666,10 +671,11 @@ fail:
 }
 
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
-		uint32_t size, struct sg_table *sgt)
+		struct dma_buf *dmabuf, struct sg_table *sgt)
 {
 	struct msm_gem_object *msm_obj;
 	struct drm_gem_object *obj;
+	uint32_t size;
 	int ret, npages;
 
 	/* if we don't have IOMMU, don't bother pretending we can import: */
@@ -678,9 +684,9 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
 		return ERR_PTR(-EINVAL);
 	}
 
-	size = PAGE_ALIGN(size);
+	size = PAGE_ALIGN(dmabuf->size);
 
-	ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);
+	ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index 121975b..6b90890 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -55,7 +55,7 @@ int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
 struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
 		struct dma_buf_attachment *attach, struct sg_table *sg)
 {
-	return msm_gem_import(dev, attach->dmabuf->size, sg);
+	return msm_gem_import(dev, attach->dmabuf, sg);
 }
 
 int msm_gem_prime_pin(struct drm_gem_object *obj)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 06/11] drm/msm: split out timeout_to_jiffies helper
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (4 preceding siblings ...)
  2016-03-18 23:14 ` [PATCH 05/11] drm/msm: use imported dmabuf's reservation object Rob Clark
@ 2016-03-18 23:14 ` Rob Clark
  2016-03-18 23:15 ` [PATCH 07/11] drm/msm/gpu: simplify tracking in-flight bo's Rob Clark
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:14 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, maarten.lankhorst, linux-arm-msm, freedreno, Rob Clark

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/msm_drv.h   | 15 +++++++++++++++
 drivers/gpu/drm/msm/msm_fence.c | 11 +----------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index fed3869..6107a39 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -335,5 +335,20 @@ static inline int align_pitch(int width, int bpp)
 /* for conditionally setting boolean flag(s): */
 #define COND(bool, val) ((bool) ? (val) : 0)
 
+static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)
+{
+	ktime_t now = ktime_get();
+	unsigned long remaining_jiffies;
+
+	if (ktime_compare(*timeout, now) < 0) {
+		remaining_jiffies = 0;
+	} else {
+		ktime_t rem = ktime_sub(*timeout, now);
+		struct timespec ts = ktime_to_timespec(rem);
+		remaining_jiffies = timespec_to_jiffies(&ts);
+	}
+
+	return remaining_jiffies;
+}
 
 #endif /* __MSM_DRV_H__ */
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index 55a5f92..002eecb 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -44,16 +44,7 @@ int msm_wait_fence(struct drm_device *dev, uint32_t fence,
 		/* no-wait: */
 		ret = fence_completed(dev, fence) ? 0 : -EBUSY;
 	} else {
-		ktime_t now = ktime_get();
-		unsigned long remaining_jiffies;
-
-		if (ktime_compare(*timeout, now) < 0) {
-			remaining_jiffies = 0;
-		} else {
-			ktime_t rem = ktime_sub(*timeout, now);
-			struct timespec ts = ktime_to_timespec(rem);
-			remaining_jiffies = timespec_to_jiffies(&ts);
-		}
+		unsigned long remaining_jiffies = timeout_to_jiffies(timeout);
 
 		if (interruptible)
 			ret = wait_event_interruptible_timeout(priv->fence_event,
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 07/11] drm/msm/gpu: simplify tracking in-flight bo's
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (5 preceding siblings ...)
  2016-03-18 23:14 ` [PATCH 06/11] drm/msm: split out timeout_to_jiffies helper Rob Clark
@ 2016-03-18 23:15 ` Rob Clark
  2016-03-18 23:15 ` [PATCH 08/11] drm/msm: split locking and pinning BO's Rob Clark
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:15 UTC (permalink / raw)
  To: dri-devel; +Cc: maarten.lankhorst, linux-arm-msm, freedreno

Since we already track the array of bo's in the submit object, just
unconditionally take and drop ref's per submit (rather than only taking
ref's if bo is not already active).  This simplifies later patches.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/msm_gpu.c | 51 +++++++++++++++++++------------------------
 1 file changed, 22 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 5f6704c..dfa72b8 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -432,6 +432,22 @@ out:
  * Cmdstream submission/retirement:
  */
 
+static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
+{
+	int i;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		/* move to inactive: */
+		msm_gem_move_to_inactive(&msm_obj->base);
+		msm_gem_put_iova(&msm_obj->base, gpu->id);
+		drm_gem_object_unreference(&msm_obj->base);
+	}
+
+	list_del(&submit->node);
+	kfree(submit);
+}
+
 static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
 {
 	struct drm_device *dev = gpu->dev;
@@ -445,8 +461,7 @@ static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
 				struct msm_gem_submit, node);
 
 		if (submit->fence <= fence) {
-			list_del(&submit->node);
-			kfree(submit);
+			retire_submit(gpu, submit);
 		} else {
 			break;
 		}
@@ -462,26 +477,7 @@ static void retire_worker(struct work_struct *work)
 	msm_update_fence(gpu->dev, fence);
 
 	mutex_lock(&dev->struct_mutex);
-
 	retire_submits(gpu, fence);
-
-	while (!list_empty(&gpu->active_list)) {
-		struct msm_gem_object *obj;
-
-		obj = list_first_entry(&gpu->active_list,
-				struct msm_gem_object, mm_list);
-
-		if ((obj->read_fence <= fence) &&
-				(obj->write_fence <= fence)) {
-			/* move to inactive: */
-			msm_gem_move_to_inactive(&obj->base);
-			msm_gem_put_iova(&obj->base, gpu->id);
-			drm_gem_object_unreference(&obj->base);
-		} else {
-			break;
-		}
-	}
-
 	mutex_unlock(&dev->struct_mutex);
 
 	if (!msm_gpu_active(gpu))
@@ -522,20 +518,17 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 
 	for (i = 0; i < submit->nr_bos; i++) {
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		uint32_t iova;
 
 		/* can't happen yet.. but when we add 2d support we'll have
 		 * to deal w/ cross-ring synchronization:
 		 */
 		WARN_ON(is_active(msm_obj) && (msm_obj->gpu != gpu));
 
-		if (!is_active(msm_obj)) {
-			uint32_t iova;
-
-			/* ring takes a reference to the bo and iova: */
-			drm_gem_object_reference(&msm_obj->base);
-			msm_gem_get_iova_locked(&msm_obj->base,
-					submit->gpu->id, &iova);
-		}
+		/* submit takes a reference to the bo and iova until retired: */
+		drm_gem_object_reference(&msm_obj->base);
+		msm_gem_get_iova_locked(&msm_obj->base,
+				submit->gpu->id, &iova);
 
 		if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
 			msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 08/11] drm/msm: split locking and pinning BO's
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (6 preceding siblings ...)
  2016-03-18 23:15 ` [PATCH 07/11] drm/msm/gpu: simplify tracking in-flight bo's Rob Clark
@ 2016-03-18 23:15 ` Rob Clark
  2016-03-18 23:15 ` [PATCH 09/11] drm/msm: introduce msm_fence_context Rob Clark
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:15 UTC (permalink / raw)
  To: dri-devel; +Cc: maarten.lankhorst, linux-arm-msm, freedreno

Split up locking and pinning buffers in the submit path.  This is needed
because we'll want to insert fencing in between the two steps.

This makes things end up looking more similar to etnaviv submit code
(which was originally modelled on the msm code but has already added
'struct fence' support).

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/msm_gem.h        |  2 +-
 drivers/gpu/drm/msm/msm_gem_submit.c | 69 ++++++++++++++++++++----------------
 2 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 6fc59bf..b890451 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -100,7 +100,7 @@ struct msm_gem_submit {
 	struct list_head bo_list;
 	struct ww_acquire_ctx ticket;
 	uint32_t fence;
-	bool valid;
+	bool valid;         /* true if no cmdstream patching needed */
 	unsigned int nr_cmds;
 	unsigned int nr_bos;
 	struct {
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 43d2181..b231544 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -24,7 +24,7 @@
  */
 
 /* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
-#define BO_VALID    0x8000
+#define BO_VALID    0x8000   /* is current addr in cmdstream correct/valid? */
 #define BO_LOCKED   0x4000
 #define BO_PINNED   0x2000
 
@@ -136,16 +136,13 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i)
 }
 
 /* This is where we make sure all the bo's are reserved and pin'd: */
-static int submit_validate_objects(struct msm_gem_submit *submit)
+static int submit_lock_objects(struct msm_gem_submit *submit)
 {
 	int contended, slow_locked = -1, i, ret = 0;
 
 retry:
-	submit->valid = true;
-
 	for (i = 0; i < submit->nr_bos; i++) {
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
-		uint32_t iova;
 
 		if (slow_locked == i)
 			slow_locked = -1;
@@ -159,30 +156,6 @@ retry:
 				goto fail;
 			submit->bos[i].flags |= BO_LOCKED;
 		}
-
-
-		/* if locking succeeded, pin bo: */
-		ret = msm_gem_get_iova_locked(&msm_obj->base,
-				submit->gpu->id, &iova);
-
-		/* this would break the logic in the fail path.. there is no
-		 * reason for this to happen, but just to be on the safe side
-		 * let's notice if this starts happening in the future:
-		 */
-		WARN_ON(ret == -EDEADLK);
-
-		if (ret)
-			goto fail;
-
-		submit->bos[i].flags |= BO_PINNED;
-
-		if (iova == submit->bos[i].iova) {
-			submit->bos[i].flags |= BO_VALID;
-		} else {
-			submit->bos[i].iova = iova;
-			submit->bos[i].flags &= ~BO_VALID;
-			submit->valid = false;
-		}
 	}
 
 	ww_acquire_done(&submit->ticket);
@@ -211,6 +184,38 @@ fail:
 	return ret;
 }
 
+static int submit_pin_objects(struct msm_gem_submit *submit)
+{
+	int i, ret = 0;
+
+	submit->valid = true;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		uint32_t iova;
+
+		/* if locking succeeded, pin bo: */
+		ret = msm_gem_get_iova_locked(&msm_obj->base,
+				submit->gpu->id, &iova);
+
+		if (ret)
+			break;
+
+		submit->bos[i].flags |= BO_PINNED;
+
+		if (iova == submit->bos[i].iova) {
+			submit->bos[i].flags |= BO_VALID;
+		} else {
+			submit->bos[i].iova = iova;
+			/* iova changed, so address in cmdstream is not valid: */
+			submit->bos[i].flags &= ~BO_VALID;
+			submit->valid = false;
+		}
+	}
+
+	return ret;
+}
+
 static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
 		struct msm_gem_object **obj, uint32_t *iova, bool *valid)
 {
@@ -349,7 +354,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 	if (ret)
 		goto out;
 
-	ret = submit_validate_objects(submit);
+	ret = submit_lock_objects(submit);
+	if (ret)
+		goto out;
+
+	ret = submit_pin_objects(submit);
 	if (ret)
 		goto out;
 
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 09/11] drm/msm: introduce msm_fence_context
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (7 preceding siblings ...)
  2016-03-18 23:15 ` [PATCH 08/11] drm/msm: split locking and pinning BO's Rob Clark
@ 2016-03-18 23:15 ` Rob Clark
  2016-03-18 23:15 ` [PATCH 10/11] drm/msm: remove fence_cbs Rob Clark
  2016-03-18 23:15 ` [PATCH 11/11] drm/msm: 'struct fence' conversion Rob Clark
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:15 UTC (permalink / raw)
  To: dri-devel; +Cc: maarten.lankhorst, linux-arm-msm, freedreno

Better encapsulate the per-timeline stuff into fence-context.  For now
there is just a single fence-context, but eventually we'll also have one
per-CRTC to enable fully explicit fencing.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/adreno/adreno_gpu.c |  6 +--
 drivers/gpu/drm/msm/msm_atomic.c        |  9 ++--
 drivers/gpu/drm/msm/msm_drv.c           |  8 +--
 drivers/gpu/drm/msm/msm_drv.h           |  7 +--
 drivers/gpu/drm/msm/msm_fence.c         | 87 ++++++++++++++++++++-------------
 drivers/gpu/drm/msm/msm_fence.h         | 21 ++++++--
 drivers/gpu/drm/msm/msm_gem.c           |  4 +-
 drivers/gpu/drm/msm/msm_gpu.c           | 23 +++++----
 drivers/gpu/drm/msm/msm_gpu.h           |  7 ++-
 9 files changed, 108 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 4951172..9aab871 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -121,7 +121,7 @@ void adreno_recover(struct msm_gpu *gpu)
 	gpu->rb->cur = gpu->rb->start;
 
 	/* reset completed fence seqno, just discard anything pending: */
-	adreno_gpu->memptrs->fence = gpu->submitted_fence;
+	adreno_gpu->memptrs->fence = gpu->fctx->last_fence;
 	adreno_gpu->memptrs->rptr  = 0;
 	adreno_gpu->memptrs->wptr  = 0;
 
@@ -254,7 +254,7 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
 			adreno_gpu->rev.patchid);
 
 	seq_printf(m, "fence:    %d/%d\n", adreno_gpu->memptrs->fence,
-			gpu->submitted_fence);
+			gpu->fctx->last_fence);
 	seq_printf(m, "rptr:     %d\n", get_rptr(adreno_gpu));
 	seq_printf(m, "wptr:     %d\n", adreno_gpu->memptrs->wptr);
 	seq_printf(m, "rb wptr:  %d\n", get_wptr(gpu->rb));
@@ -295,7 +295,7 @@ void adreno_dump_info(struct msm_gpu *gpu)
 			adreno_gpu->rev.patchid);
 
 	printk("fence:    %d/%d\n", adreno_gpu->memptrs->fence,
-			gpu->submitted_fence);
+			gpu->fctx->last_fence);
 	printk("rptr:     %d\n", get_rptr(adreno_gpu));
 	printk("wptr:     %d\n", adreno_gpu->memptrs->wptr);
 	printk("rb wptr:  %d\n", get_wptr(gpu->rb));
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 3c0f7a8..61f59db 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -18,6 +18,7 @@
 #include "msm_drv.h"
 #include "msm_kms.h"
 #include "msm_gem.h"
+#include "msm_gpu.h"   /* temporary */
 #include "msm_fence.h"
 
 struct msm_commit {
@@ -203,6 +204,7 @@ int msm_atomic_check(struct drm_device *dev,
 int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool async)
 {
+	struct msm_drm_private *priv = dev->dev_private;
 	int nplanes = dev->mode_config.num_total_plane;
 	int ncrtcs = dev->mode_config.num_crtc;
 	ktime_t timeout;
@@ -277,15 +279,16 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * current layout.
 	 */
 
-	if (async) {
-		msm_queue_fence_cb(dev, &c->fence_cb, c->fence);
+	if (async && priv->gpu) {
+		msm_queue_fence_cb(priv->gpu->fctx, &c->fence_cb, c->fence);
 		return 0;
 	}
 
 	timeout = ktime_add_ms(ktime_get(), 1000);
 
 	/* uninterruptible wait */
-	msm_wait_fence(dev, c->fence, &timeout, false);
+	if (priv->gpu)
+		msm_wait_fence(priv->gpu->fctx, c->fence, &timeout, false);
 
 	complete_commit(c);
 
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 6988285..b623397 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -339,11 +339,9 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
 	dev->dev_private = priv;
 
 	priv->wq = alloc_ordered_workqueue("msm", 0);
-	init_waitqueue_head(&priv->fence_event);
 	init_waitqueue_head(&priv->pending_crtcs_event);
 
 	INIT_LIST_HEAD(&priv->inactive_list);
-	INIT_LIST_HEAD(&priv->fence_cbs);
 	INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
 	INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker);
 	spin_lock_init(&priv->vblank_ctrl.lock);
@@ -650,6 +648,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
 static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
 		struct drm_file *file)
 {
+	struct msm_drm_private *priv = dev->dev_private;
 	struct drm_msm_wait_fence *args = data;
 	ktime_t timeout = to_ktime(args->timeout);
 
@@ -658,7 +657,10 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
 		return -EINVAL;
 	}
 
-	return msm_wait_fence(dev, args->fence, &timeout, true);
+	if (!priv->gpu)
+		return 0;
+
+	return msm_wait_fence(priv->gpu->fctx, args->fence, &timeout, true);
 }
 
 static const struct drm_ioctl_desc msm_ioctls[] = {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6107a39..3df747f 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -49,6 +49,7 @@ struct msm_mmu;
 struct msm_rd_state;
 struct msm_perf_state;
 struct msm_gem_submit;
+struct msm_fence_context;
 struct msm_fence_cb;
 
 #define NUM_DOMAINS 2    /* one for KMS, then one per gpu core (?) */
@@ -101,9 +102,6 @@ struct msm_drm_private {
 
 	struct drm_fb_helper *fbdev;
 
-	uint32_t next_fence, completed_fence;
-	wait_queue_head_t fence_event;
-
 	struct msm_rd_state *rd;
 	struct msm_perf_state *perf;
 
@@ -112,9 +110,6 @@ struct msm_drm_private {
 
 	struct workqueue_struct *wq;
 
-	/* callbacks deferred until bo is inactive: */
-	struct list_head fence_cbs;
-
 	/* crtcs pending async atomic updates: */
 	uint32_t pending_crtcs;
 	wait_queue_head_t pending_crtcs_event;
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index 002eecb..f0ed6a6 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -15,49 +15,68 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/fence.h>
+
 #include "msm_drv.h"
 #include "msm_fence.h"
-#include "msm_gpu.h"
 
-static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
+
+struct msm_fence_context *
+msm_fence_context_alloc(struct drm_device *dev, const char *name)
 {
-	struct msm_drm_private *priv = dev->dev_private;
-	return (int32_t)(priv->completed_fence - fence) >= 0;
+	struct msm_fence_context *fctx;
+
+	fctx = kzalloc(sizeof(*fctx), GFP_KERNEL);
+	if (!fctx)
+		return ERR_PTR(-ENOMEM);
+
+	fctx->dev = dev;
+	fctx->name = name;
+	init_waitqueue_head(&fctx->event);
+	INIT_LIST_HEAD(&fctx->fence_cbs);
+
+	return fctx;
 }
 
-int msm_wait_fence(struct drm_device *dev, uint32_t fence,
-		ktime_t *timeout , bool interruptible)
+void msm_fence_context_free(struct msm_fence_context *fctx)
 {
-	struct msm_drm_private *priv = dev->dev_private;
-	int ret;
+	kfree(fctx);
+}
+
+static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fence)
+{
+	return (int32_t)(fctx->completed_fence - fence) >= 0;
+}
 
-	if (!priv->gpu)
-		return 0;
+int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
+		ktime_t *timeout, bool interruptible)
+{
+	int ret;
 
-	if (fence > priv->gpu->submitted_fence) {
-		DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
-				fence, priv->gpu->submitted_fence);
+	if (fence > fctx->last_fence) {
+		DRM_ERROR("%s: waiting on invalid fence: %u (of %u)\n",
+				fctx->name, fence, fctx->last_fence);
 		return -EINVAL;
 	}
 
 	if (!timeout) {
 		/* no-wait: */
-		ret = fence_completed(dev, fence) ? 0 : -EBUSY;
+		ret = fence_completed(fctx, fence) ? 0 : -EBUSY;
 	} else {
 		unsigned long remaining_jiffies = timeout_to_jiffies(timeout);
 
 		if (interruptible)
-			ret = wait_event_interruptible_timeout(priv->fence_event,
-				fence_completed(dev, fence),
+			ret = wait_event_interruptible_timeout(fctx->event,
+				fence_completed(fctx, fence),
 				remaining_jiffies);
 		else
-			ret = wait_event_timeout(priv->fence_event,
-				fence_completed(dev, fence),
+			ret = wait_event_timeout(fctx->event,
+				fence_completed(fctx, fence),
 				remaining_jiffies);
 
 		if (ret == 0) {
 			DBG("timeout waiting for fence: %u (completed: %u)",
-					fence, priv->completed_fence);
+					fence, fctx->completed_fence);
 			ret = -ETIMEDOUT;
 		} else if (ret != -ERESTARTSYS) {
 			ret = 0;
@@ -67,50 +86,50 @@ int msm_wait_fence(struct drm_device *dev, uint32_t fence,
 	return ret;
 }
 
-int msm_queue_fence_cb(struct drm_device *dev,
+int msm_queue_fence_cb(struct msm_fence_context *fctx,
 		struct msm_fence_cb *cb, uint32_t fence)
 {
-	struct msm_drm_private *priv = dev->dev_private;
+	struct msm_drm_private *priv = fctx->dev->dev_private;
 	int ret = 0;
 
-	mutex_lock(&dev->struct_mutex);
+	mutex_lock(&fctx->dev->struct_mutex);
 	if (!list_empty(&cb->work.entry)) {
 		ret = -EINVAL;
-	} else if (fence > priv->completed_fence) {
+	} else if (fence > fctx->completed_fence) {
 		cb->fence = fence;
-		list_add_tail(&cb->work.entry, &priv->fence_cbs);
+		list_add_tail(&cb->work.entry, &fctx->fence_cbs);
 	} else {
 		queue_work(priv->wq, &cb->work);
 	}
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&fctx->dev->struct_mutex);
 
 	return ret;
 }
 
 /* called from workqueue */
-void msm_update_fence(struct drm_device *dev, uint32_t fence)
+void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
 {
-	struct msm_drm_private *priv = dev->dev_private;
+	struct msm_drm_private *priv = fctx->dev->dev_private;
 
-	mutex_lock(&dev->struct_mutex);
-	priv->completed_fence = max(fence, priv->completed_fence);
+	mutex_lock(&fctx->dev->struct_mutex);
+	fctx->completed_fence = max(fence, fctx->completed_fence);
 
-	while (!list_empty(&priv->fence_cbs)) {
+	while (!list_empty(&fctx->fence_cbs)) {
 		struct msm_fence_cb *cb;
 
-		cb = list_first_entry(&priv->fence_cbs,
+		cb = list_first_entry(&fctx->fence_cbs,
 				struct msm_fence_cb, work.entry);
 
-		if (cb->fence > priv->completed_fence)
+		if (cb->fence > fctx->completed_fence)
 			break;
 
 		list_del_init(&cb->work.entry);
 		queue_work(priv->wq, &cb->work);
 	}
 
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&fctx->dev->struct_mutex);
 
-	wake_up_all(&priv->fence_event);
+	wake_up_all(&fctx->event);
 }
 
 void __msm_fence_worker(struct work_struct *work)
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index 6ddb81c..3ed2098 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -20,6 +20,21 @@
 
 #include "msm_drv.h"
 
+struct msm_fence_context {
+	struct drm_device *dev;
+	const char *name;
+	/* last_fence == completed_fence --> no pending work */
+	uint32_t last_fence;          /* last assigned fence */
+	uint32_t completed_fence;     /* last completed fence */
+	wait_queue_head_t event;
+	/* callbacks deferred until bo is inactive: */
+	struct list_head fence_cbs;
+};
+
+struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
+		const char *name);
+void msm_fence_context_free(struct msm_fence_context *fctx);
+
 /* callback from wq once fence has passed: */
 struct msm_fence_cb {
 	struct work_struct work;
@@ -34,10 +49,10 @@ void __msm_fence_worker(struct work_struct *work);
 		(_cb)->func = _func;                         \
 	} while (0)
 
-int msm_wait_fence(struct drm_device *dev, uint32_t fence,
+int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
 		ktime_t *timeout, bool interruptible);
-int msm_queue_fence_cb(struct drm_device *dev,
+int msm_queue_fence_cb(struct msm_fence_context *fctx,
 		struct msm_fence_cb *cb, uint32_t fence);
-void msm_update_fence(struct drm_device *dev, uint32_t fence);
+void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
 
 #endif
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 09e2190..80bb6e2 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -454,6 +454,7 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
 int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 {
 	struct drm_device *dev = obj->dev;
+	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	int ret = 0;
 
@@ -463,7 +464,8 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 		if (op & MSM_PREP_NOSYNC)
 			timeout = NULL;
 
-		ret = msm_wait_fence(dev, fence, timeout, true);
+		if (priv->gpu)
+			ret = msm_wait_fence(priv->gpu->fctx, fence, timeout, true);
 	}
 
 	/* TODO cache maintenance */
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index dfa72b8..e04bd2f 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -313,7 +313,7 @@ static void hangcheck_handler(unsigned long data)
 	if (fence != gpu->hangcheck_fence) {
 		/* some progress has been made.. ya! */
 		gpu->hangcheck_fence = fence;
-	} else if (fence < gpu->submitted_fence) {
+	} else if (fence < gpu->fctx->last_fence) {
 		/* no progress and not done.. hung! */
 		gpu->hangcheck_fence = fence;
 		dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n",
@@ -321,12 +321,12 @@ static void hangcheck_handler(unsigned long data)
 		dev_err(dev->dev, "%s:     completed fence: %u\n",
 				gpu->name, fence);
 		dev_err(dev->dev, "%s:     submitted fence: %u\n",
-				gpu->name, gpu->submitted_fence);
+				gpu->name, gpu->fctx->last_fence);
 		queue_work(priv->wq, &gpu->recover_work);
 	}
 
 	/* if still more pending work, reset the hangcheck timer: */
-	if (gpu->submitted_fence > gpu->hangcheck_fence)
+	if (gpu->fctx->last_fence > gpu->hangcheck_fence)
 		hangcheck_timer_reset(gpu);
 
 	/* workaround for missing irq: */
@@ -474,7 +474,7 @@ static void retire_worker(struct work_struct *work)
 	struct drm_device *dev = gpu->dev;
 	uint32_t fence = gpu->funcs->last_fence(gpu);
 
-	msm_update_fence(gpu->dev, fence);
+	msm_update_fence(gpu->fctx, fence);
 
 	mutex_lock(&dev->struct_mutex);
 	retire_submits(gpu, fence);
@@ -502,9 +502,7 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	submit->fence = ++priv->next_fence;
-
-	gpu->submitted_fence = submit->fence;
+	submit->fence = ++gpu->fctx->last_fence;
 
 	inactive_cancel(gpu);
 
@@ -512,8 +510,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 
 	msm_rd_dump_submit(submit);
 
-	gpu->submitted_fence = submit->fence;
-
 	update_sw_cntrs(gpu);
 
 	for (i = 0; i < submit->nr_bos; i++) {
@@ -574,6 +570,12 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 	gpu->funcs = funcs;
 	gpu->name = name;
 	gpu->inactive = true;
+	gpu->fctx = msm_fence_context_alloc(drm, name);
+	if (IS_ERR(gpu->fctx)) {
+		ret = PTR_ERR(gpu->fctx);
+		gpu->fctx = NULL;
+		goto fail;
+	}
 
 	INIT_LIST_HEAD(&gpu->active_list);
 	INIT_WORK(&gpu->retire_work, retire_worker);
@@ -702,4 +704,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
 
 	if (gpu->mmu)
 		gpu->mmu->funcs->destroy(gpu->mmu);
+
+	if (gpu->fctx)
+		msm_fence_context_free(gpu->fctx);
 }
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 2bbe85a..025e25b 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -22,6 +22,7 @@
 #include <linux/regulator/consumer.h>
 
 #include "msm_drv.h"
+#include "msm_fence.h"
 #include "msm_ringbuffer.h"
 
 struct msm_gem_submit;
@@ -77,13 +78,15 @@ struct msm_gpu {
 	const struct msm_gpu_perfcntr *perfcntrs;
 	uint32_t num_perfcntrs;
 
+	/* ringbuffer: */
 	struct msm_ringbuffer *rb;
 	uint32_t rb_iova;
 
 	/* list of GEM active objects: */
 	struct list_head active_list;
 
-	uint32_t submitted_fence;
+	/* fencing: */
+	struct msm_fence_context *fctx;
 
 	/* is gpu powered/active? */
 	int active_cnt;
@@ -125,7 +128,7 @@ struct msm_gpu {
 
 static inline bool msm_gpu_active(struct msm_gpu *gpu)
 {
-	return gpu->submitted_fence > gpu->funcs->last_fence(gpu);
+	return gpu->fctx->last_fence > gpu->funcs->last_fence(gpu);
 }
 
 /* Perf-Counters:
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 10/11] drm/msm: remove fence_cbs
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (8 preceding siblings ...)
  2016-03-18 23:15 ` [PATCH 09/11] drm/msm: introduce msm_fence_context Rob Clark
@ 2016-03-18 23:15 ` Rob Clark
  2016-03-18 23:15 ` [PATCH 11/11] drm/msm: 'struct fence' conversion Rob Clark
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:15 UTC (permalink / raw)
  To: dri-devel; +Cc: maarten.lankhorst, linux-arm-msm, freedreno

This was only used for atomic commit these days.  So instead just give
atomic it's own work-queue where we can do a block on each bo in turn.
Simplifies things a whole bunch and makes the 'struct fence' conversion
easier.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/msm_atomic.c | 77 +++++++++++++++++-----------------------
 drivers/gpu/drm/msm/msm_drv.c    |  4 +++
 drivers/gpu/drm/msm/msm_drv.h    |  5 +--
 drivers/gpu/drm/msm/msm_fence.c  | 43 ----------------------
 drivers/gpu/drm/msm/msm_fence.h  | 16 ---------
 drivers/gpu/drm/msm/msm_gem.c    |  9 ++++-
 6 files changed, 47 insertions(+), 107 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 61f59db..7fc719d 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -18,18 +18,16 @@
 #include "msm_drv.h"
 #include "msm_kms.h"
 #include "msm_gem.h"
-#include "msm_gpu.h"   /* temporary */
 #include "msm_fence.h"
 
 struct msm_commit {
 	struct drm_device *dev;
 	struct drm_atomic_state *state;
-	uint32_t fence;
-	struct msm_fence_cb fence_cb;
+	struct work_struct work;
 	uint32_t crtc_mask;
 };
 
-static void fence_cb(struct msm_fence_cb *cb);
+static void commit_worker(struct work_struct *work);
 
 /* block until specified crtcs are no longer pending update, and
  * atomically mark them as pending update
@@ -71,11 +69,7 @@ static struct msm_commit *commit_init(struct drm_atomic_state *state)
 	c->dev = state->dev;
 	c->state = state;
 
-	/* TODO we might need a way to indicate to run the cb on a
-	 * different wq so wait_for_vblanks() doesn't block retiring
-	 * bo's..
-	 */
-	INIT_FENCE_CB(&c->fence_cb, fence_cb);
+	INIT_WORK(&c->work, commit_worker);
 
 	return c;
 }
@@ -113,16 +107,39 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
 	}
 }
 
+static void wait_fences(struct msm_commit *c, bool async)
+{
+	int nplanes = c->dev->mode_config.num_total_plane;
+	ktime_t timeout = ktime_add_ms(ktime_get(), 1000);
+	int i;
+
+	for (i = 0; i < nplanes; i++) {
+		struct drm_plane *plane = c->state->planes[i];
+		struct drm_plane_state *new_state = c->state->plane_states[i];
+
+		if (!plane)
+			continue;
+
+		if ((plane->state->fb != new_state->fb) && new_state->fb) {
+			struct drm_gem_object *obj =
+				msm_framebuffer_bo(new_state->fb, 0);
+			msm_gem_cpu_sync(obj, MSM_PREP_READ, &timeout);
+		}
+	}
+}
+
 /* The (potentially) asynchronous part of the commit.  At this point
  * nothing can fail short of armageddon.
  */
-static void complete_commit(struct msm_commit *c)
+static void complete_commit(struct msm_commit *c, bool async)
 {
 	struct drm_atomic_state *state = c->state;
 	struct drm_device *dev = state->dev;
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_kms *kms = priv->kms;
 
+	wait_fences(c, async);
+
 	kms->funcs->prepare_commit(kms, state);
 
 	drm_atomic_helper_commit_modeset_disables(dev, state);
@@ -155,17 +172,9 @@ static void complete_commit(struct msm_commit *c)
 	commit_destroy(c);
 }
 
-static void fence_cb(struct msm_fence_cb *cb)
+static void commit_worker(struct work_struct *work)
 {
-	struct msm_commit *c =
-			container_of(cb, struct msm_commit, fence_cb);
-	complete_commit(c);
-}
-
-static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)
-{
-	struct drm_gem_object *obj = msm_framebuffer_bo(fb, 0);
-	c->fence = max(c->fence, msm_gem_fence(to_msm_bo(obj), MSM_PREP_READ));
+	complete_commit(container_of(work, struct msm_commit, work), true);
 }
 
 int msm_atomic_check(struct drm_device *dev,
@@ -205,9 +214,7 @@ int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool async)
 {
 	struct msm_drm_private *priv = dev->dev_private;
-	int nplanes = dev->mode_config.num_total_plane;
 	int ncrtcs = dev->mode_config.num_crtc;
-	ktime_t timeout;
 	struct msm_commit *c;
 	int i, ret;
 
@@ -232,20 +239,6 @@ int msm_atomic_commit(struct drm_device *dev,
 	}
 
 	/*
-	 * Figure out what fence to wait for:
-	 */
-	for (i = 0; i < nplanes; i++) {
-		struct drm_plane *plane = state->planes[i];
-		struct drm_plane_state *new_state = state->plane_states[i];
-
-		if (!plane)
-			continue;
-
-		if ((plane->state->fb != new_state->fb) && new_state->fb)
-			add_fb(c, new_state->fb);
-	}
-
-	/*
 	 * Wait for pending updates on any of the same crtc's and then
 	 * mark our set of crtc's as busy:
 	 */
@@ -279,18 +272,12 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * current layout.
 	 */
 
-	if (async && priv->gpu) {
-		msm_queue_fence_cb(priv->gpu->fctx, &c->fence_cb, c->fence);
+	if (async) {
+		queue_work(priv->atomic_wq, &c->work);
 		return 0;
 	}
 
-	timeout = ktime_add_ms(ktime_get(), 1000);
-
-	/* uninterruptible wait */
-	if (priv->gpu)
-		msm_wait_fence(priv->gpu->fctx, c->fence, &timeout, false);
-
-	complete_commit(c);
+	complete_commit(c, false);
 
 	return 0;
 
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index b623397..281f912 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -213,6 +213,9 @@ static int msm_unload(struct drm_device *dev)
 	flush_workqueue(priv->wq);
 	destroy_workqueue(priv->wq);
 
+	flush_workqueue(priv->atomic_wq);
+	destroy_workqueue(priv->atomic_wq);
+
 	if (kms) {
 		pm_runtime_disable(dev->dev);
 		kms->funcs->destroy(kms);
@@ -339,6 +342,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
 	dev->dev_private = priv;
 
 	priv->wq = alloc_ordered_workqueue("msm", 0);
+	priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
 	init_waitqueue_head(&priv->pending_crtcs_event);
 
 	INIT_LIST_HEAD(&priv->inactive_list);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 3df747f..6194450 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -109,6 +109,7 @@ struct msm_drm_private {
 	struct list_head inactive_list;
 
 	struct workqueue_struct *wq;
+	struct workqueue_struct *atomic_wq;
 
 	/* crtcs pending async atomic updates: */
 	uint32_t pending_crtcs;
@@ -194,8 +195,8 @@ int msm_gem_queue_inactive_cb(struct drm_gem_object *obj,
 void msm_gem_move_to_active(struct drm_gem_object *obj,
 		struct msm_gpu *gpu, bool write, uint32_t fence);
 void msm_gem_move_to_inactive(struct drm_gem_object *obj);
-int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
-		ktime_t *timeout);
+int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
+int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
 int msm_gem_cpu_fini(struct drm_gem_object *obj);
 void msm_gem_free_object(struct drm_gem_object *obj);
 int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index f0ed6a6..088610c 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -33,7 +33,6 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name)
 	fctx->dev = dev;
 	fctx->name = name;
 	init_waitqueue_head(&fctx->event);
-	INIT_LIST_HEAD(&fctx->fence_cbs);
 
 	return fctx;
 }
@@ -86,54 +85,12 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
 	return ret;
 }
 
-int msm_queue_fence_cb(struct msm_fence_context *fctx,
-		struct msm_fence_cb *cb, uint32_t fence)
-{
-	struct msm_drm_private *priv = fctx->dev->dev_private;
-	int ret = 0;
-
-	mutex_lock(&fctx->dev->struct_mutex);
-	if (!list_empty(&cb->work.entry)) {
-		ret = -EINVAL;
-	} else if (fence > fctx->completed_fence) {
-		cb->fence = fence;
-		list_add_tail(&cb->work.entry, &fctx->fence_cbs);
-	} else {
-		queue_work(priv->wq, &cb->work);
-	}
-	mutex_unlock(&fctx->dev->struct_mutex);
-
-	return ret;
-}
-
 /* called from workqueue */
 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
 {
-	struct msm_drm_private *priv = fctx->dev->dev_private;
-
 	mutex_lock(&fctx->dev->struct_mutex);
 	fctx->completed_fence = max(fence, fctx->completed_fence);
-
-	while (!list_empty(&fctx->fence_cbs)) {
-		struct msm_fence_cb *cb;
-
-		cb = list_first_entry(&fctx->fence_cbs,
-				struct msm_fence_cb, work.entry);
-
-		if (cb->fence > fctx->completed_fence)
-			break;
-
-		list_del_init(&cb->work.entry);
-		queue_work(priv->wq, &cb->work);
-	}
-
 	mutex_unlock(&fctx->dev->struct_mutex);
 
 	wake_up_all(&fctx->event);
 }
-
-void __msm_fence_worker(struct work_struct *work)
-{
-	struct msm_fence_cb *cb = container_of(work, struct msm_fence_cb, work);
-	cb->func(cb);
-}
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index 3ed2098..2820781 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -27,28 +27,12 @@ struct msm_fence_context {
 	uint32_t last_fence;          /* last assigned fence */
 	uint32_t completed_fence;     /* last completed fence */
 	wait_queue_head_t event;
-	/* callbacks deferred until bo is inactive: */
-	struct list_head fence_cbs;
 };
 
 struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
 		const char *name);
 void msm_fence_context_free(struct msm_fence_context *fctx);
 
-/* callback from wq once fence has passed: */
-struct msm_fence_cb {
-	struct work_struct work;
-	uint32_t fence;
-	void (*func)(struct msm_fence_cb *cb);
-};
-
-void __msm_fence_worker(struct work_struct *work);
-
-#define INIT_FENCE_CB(_cb, _func)  do {                     \
-		INIT_WORK(&(_cb)->work, __msm_fence_worker); \
-		(_cb)->func = _func;                         \
-	} while (0)
-
 int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
 		ktime_t *timeout, bool interruptible);
 int msm_queue_fence_cb(struct msm_fence_context *fctx,
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 80bb6e2..1aabc41 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -451,7 +451,7 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
 	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
 }
 
-int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
+int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 {
 	struct drm_device *dev = obj->dev;
 	struct msm_drm_private *priv = dev->dev_private;
@@ -468,6 +468,13 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 			ret = msm_wait_fence(priv->gpu->fctx, fence, timeout, true);
 	}
 
+	return ret;
+}
+
+int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
+{
+	int ret = msm_gem_cpu_sync(obj, op, timeout);
+
 	/* TODO cache maintenance */
 
 	return ret;
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 11/11] drm/msm: 'struct fence' conversion
  2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
                   ` (9 preceding siblings ...)
  2016-03-18 23:15 ` [PATCH 10/11] drm/msm: remove fence_cbs Rob Clark
@ 2016-03-18 23:15 ` Rob Clark
  10 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2016-03-18 23:15 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, maarten.lankhorst, linux-arm-msm, freedreno, Rob Clark

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/msm/adreno/adreno_gpu.c |   4 +-
 drivers/gpu/drm/msm/msm_atomic.c        |  42 ++++++-----
 drivers/gpu/drm/msm/msm_drv.h           |   5 +-
 drivers/gpu/drm/msm/msm_fence.c         |  71 +++++++++++++++++-
 drivers/gpu/drm/msm/msm_fence.h         |   4 ++
 drivers/gpu/drm/msm/msm_gem.c           | 124 ++++++++++++++++++++++++--------
 drivers/gpu/drm/msm/msm_gem.h           |  16 +----
 drivers/gpu/drm/msm/msm_gem_submit.c    |  22 +++++-
 drivers/gpu/drm/msm/msm_gpu.c           |  27 ++++---
 drivers/gpu/drm/msm/msm_rd.c            |   2 +-
 10 files changed, 233 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 9aab871..95aed37 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -168,7 +168,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 		OUT_PKT2(ring);
 
 	OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
-	OUT_RING(ring, submit->fence);
+	OUT_RING(ring, submit->fence->seqno);
 
 	if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) {
 		/* Flush HLSQ lazy updates to make sure there is nothing
@@ -185,7 +185,7 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 	OUT_PKT3(ring, CP_EVENT_WRITE, 3);
 	OUT_RING(ring, CACHE_FLUSH_TS);
 	OUT_RING(ring, rbmemptr(adreno_gpu, fence));
-	OUT_RING(ring, submit->fence);
+	OUT_RING(ring, submit->fence->seqno);
 
 	/* we could maybe be clever and only CP_COND_EXEC the interrupt: */
 	OUT_PKT3(ring, CP_INTERRUPT, 1);
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 7fc719d..5f6fc19 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -107,27 +107,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
 	}
 }
 
-static void wait_fences(struct msm_commit *c, bool async)
-{
-	int nplanes = c->dev->mode_config.num_total_plane;
-	ktime_t timeout = ktime_add_ms(ktime_get(), 1000);
-	int i;
-
-	for (i = 0; i < nplanes; i++) {
-		struct drm_plane *plane = c->state->planes[i];
-		struct drm_plane_state *new_state = c->state->plane_states[i];
-
-		if (!plane)
-			continue;
-
-		if ((plane->state->fb != new_state->fb) && new_state->fb) {
-			struct drm_gem_object *obj =
-				msm_framebuffer_bo(new_state->fb, 0);
-			msm_gem_cpu_sync(obj, MSM_PREP_READ, &timeout);
-		}
-	}
-}
-
 /* The (potentially) asynchronous part of the commit.  At this point
  * nothing can fail short of armageddon.
  */
@@ -138,7 +117,7 @@ static void complete_commit(struct msm_commit *c, bool async)
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_kms *kms = priv->kms;
 
-	wait_fences(c, async);
+	drm_atomic_helper_wait_for_fences(dev, state);
 
 	kms->funcs->prepare_commit(kms, state);
 
@@ -214,6 +193,7 @@ int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool async)
 {
 	struct msm_drm_private *priv = dev->dev_private;
+	int nplanes = dev->mode_config.num_total_plane;
 	int ncrtcs = dev->mode_config.num_crtc;
 	struct msm_commit *c;
 	int i, ret;
@@ -239,6 +219,24 @@ int msm_atomic_commit(struct drm_device *dev,
 	}
 
 	/*
+	 * Figure out what fence to wait for:
+	 */
+	for (i = 0; i < nplanes; i++) {
+		struct drm_plane *plane = state->planes[i];
+		struct drm_plane_state *new_state = state->plane_states[i];
+
+		if (!plane)
+			continue;
+
+		if ((plane->state->fb != new_state->fb) && new_state->fb) {
+			struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0);
+			struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+			new_state->fence = reservation_object_get_excl_unlocked(msm_obj->resv);
+		}
+	}
+
+	/*
 	 * Wait for pending updates on any of the same crtc's and then
 	 * mark our set of crtc's as busy:
 	 */
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6194450..1ad6c79 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -192,10 +192,11 @@ void *msm_gem_vaddr_locked(struct drm_gem_object *obj);
 void *msm_gem_vaddr(struct drm_gem_object *obj);
 int msm_gem_queue_inactive_cb(struct drm_gem_object *obj,
 		struct msm_fence_cb *cb);
+int msm_gem_sync_object(struct drm_gem_object *obj,
+		struct msm_fence_context *fctx, bool exclusive);
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-		struct msm_gpu *gpu, bool write, uint32_t fence);
+		struct msm_gpu *gpu, bool exclusive, struct fence *fence);
 void msm_gem_move_to_inactive(struct drm_gem_object *obj);
-int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
 int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
 int msm_gem_cpu_fini(struct drm_gem_object *obj);
 void msm_gem_free_object(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c
index 088610c..a9b9b1c 100644
--- a/drivers/gpu/drm/msm/msm_fence.c
+++ b/drivers/gpu/drm/msm/msm_fence.c
@@ -32,7 +32,9 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name)
 
 	fctx->dev = dev;
 	fctx->name = name;
+	fctx->context = fence_context_alloc(1);
 	init_waitqueue_head(&fctx->event);
+	spin_lock_init(&fctx->spinlock);
 
 	return fctx;
 }
@@ -47,6 +49,7 @@ static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fenc
 	return (int32_t)(fctx->completed_fence - fence) >= 0;
 }
 
+/* legacy path for WAIT_FENCE ioctl: */
 int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
 		ktime_t *timeout, bool interruptible)
 {
@@ -88,9 +91,73 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
 /* called from workqueue */
 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
 {
-	mutex_lock(&fctx->dev->struct_mutex);
+	spin_lock(&fctx->spinlock);
 	fctx->completed_fence = max(fence, fctx->completed_fence);
-	mutex_unlock(&fctx->dev->struct_mutex);
+	spin_unlock(&fctx->spinlock);
 
 	wake_up_all(&fctx->event);
 }
+
+struct msm_fence {
+	struct msm_fence_context *fctx;
+	struct fence base;
+};
+
+static inline struct msm_fence *to_msm_fence(struct fence *fence)
+{
+	return container_of(fence, struct msm_fence, base);
+}
+
+static const char *msm_fence_get_driver_name(struct fence *fence)
+{
+	return "msm";
+}
+
+static const char *msm_fence_get_timeline_name(struct fence *fence)
+{
+	struct msm_fence *f = to_msm_fence(fence);
+	return f->fctx->name;
+}
+
+static bool msm_fence_enable_signaling(struct fence *fence)
+{
+	return true;
+}
+
+static bool msm_fence_signaled(struct fence *fence)
+{
+	struct msm_fence *f = to_msm_fence(fence);
+	return fence_completed(f->fctx, f->base.seqno);
+}
+
+static void msm_fence_release(struct fence *fence)
+{
+	struct msm_fence *f = to_msm_fence(fence);
+	kfree_rcu(f, base.rcu);
+}
+
+static const struct fence_ops msm_fence_ops = {
+	.get_driver_name = msm_fence_get_driver_name,
+	.get_timeline_name = msm_fence_get_timeline_name,
+	.enable_signaling = msm_fence_enable_signaling,
+	.signaled = msm_fence_signaled,
+	.wait = fence_default_wait,
+	.release = msm_fence_release,
+};
+
+struct fence *
+msm_fence_alloc(struct msm_fence_context *fctx)
+{
+	struct msm_fence *f;
+
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
+	if (!f)
+		return ERR_PTR(-ENOMEM);
+
+	f->fctx = fctx;
+
+	fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
+			fctx->context, ++fctx->last_fence);
+
+	return &f->base;
+}
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index 2820781..ceb5b3d 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -23,10 +23,12 @@
 struct msm_fence_context {
 	struct drm_device *dev;
 	const char *name;
+	unsigned context;
 	/* last_fence == completed_fence --> no pending work */
 	uint32_t last_fence;          /* last assigned fence */
 	uint32_t completed_fence;     /* last completed fence */
 	wait_queue_head_t event;
+	spinlock_t spinlock;
 };
 
 struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
@@ -39,4 +41,6 @@ int msm_queue_fence_cb(struct msm_fence_context *fctx,
 		struct msm_fence_cb *cb, uint32_t fence);
 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
 
+struct fence * msm_fence_alloc(struct msm_fence_context *fctx);
+
 #endif
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 1aabc41..00b718e 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -423,15 +423,62 @@ int msm_gem_queue_inactive_cb(struct drm_gem_object *obj,
 	return msm_queue_fence_cb(obj->dev, cb, fence);
 }
 
+/* must be called before _move_to_active().. */
+int msm_gem_sync_object(struct drm_gem_object *obj,
+		struct msm_fence_context *fctx, bool exclusive)
+{
+	struct msm_gem_object *msm_obj = to_msm_bo(obj);
+	struct reservation_object_list *fobj;
+	struct fence *fence;
+	int i, ret;
+
+	if (!exclusive) {
+		/* NOTE: _reserve_shared() must happen before _add_shared_fence(),
+		 * which makes this a slightly strange place to call it.  OTOH this
+		 * is a convenient can-fail point to hook it in.  (And similar to
+		 * how etnaviv and nouveau handle this.)
+		 */
+		ret = reservation_object_reserve_shared(msm_obj->resv);
+		if (ret)
+			return ret;
+	}
+
+	fobj = reservation_object_get_list(msm_obj->resv);
+	if (!fobj || (fobj->shared_count == 0)) {
+		fence = reservation_object_get_excl(msm_obj->resv);
+		/* don't need to wait on our own fences, since ring is fifo */
+		if (fence && (fence->context != fctx->context)) {
+			ret = fence_wait(fence, true);
+			if (ret)
+				return ret;
+		}
+	}
+
+	if (!exclusive || !fobj)
+		return 0;
+
+	for (i = 0; i < fobj->shared_count; i++) {
+		fence = rcu_dereference_protected(fobj->shared[i],
+						reservation_object_held(msm_obj->resv));
+		if (fence->context != fctx->context) {
+			ret = fence_wait(fence, true);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-		struct msm_gpu *gpu, bool write, uint32_t fence)
+		struct msm_gpu *gpu, bool exclusive, struct fence *fence)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	msm_obj->gpu = gpu;
-	if (write)
-		msm_obj->write_fence = fence;
+	if (exclusive)
+		reservation_object_add_excl_fence(msm_obj->resv, fence);
 	else
-		msm_obj->read_fence = fence;
+		reservation_object_add_shared_fence(msm_obj->resv, fence);
 	list_del_init(&msm_obj->mm_list);
 	list_add_tail(&msm_obj->mm_list, &gpu->active_list);
 }
@@ -445,39 +492,30 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
 	msm_obj->gpu = NULL;
-	msm_obj->read_fence = 0;
-	msm_obj->write_fence = 0;
 	list_del_init(&msm_obj->mm_list);
 	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
 }
 
-int msm_gem_cpu_sync(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
+int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 {
-	struct drm_device *dev = obj->dev;
-	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
-	int ret = 0;
-
-	if (is_active(msm_obj)) {
-		uint32_t fence = msm_gem_fence(msm_obj, op);
+	bool write = !!(op & MSM_PREP_WRITE);
 
-		if (op & MSM_PREP_NOSYNC)
-			timeout = NULL;
+	if (op & MSM_PREP_NOSYNC) {
+		if (!reservation_object_test_signaled_rcu(msm_obj->resv, write))
+			return -EBUSY;
+	} else {
+		int ret;
 
-		if (priv->gpu)
-			ret = msm_wait_fence(priv->gpu->fctx, fence, timeout, true);
+		ret = reservation_object_wait_timeout_rcu(msm_obj->resv, write,
+				true, timeout_to_jiffies(timeout));
+		if (ret <= 0)
+			return ret == 0 ? -ETIMEDOUT : ret;
 	}
 
-	return ret;
-}
-
-int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
-{
-	int ret = msm_gem_cpu_sync(obj, op, timeout);
-
 	/* TODO cache maintenance */
 
-	return ret;
+	return 0;
 }
 
 int msm_gem_cpu_fini(struct drm_gem_object *obj)
@@ -487,18 +525,46 @@ int msm_gem_cpu_fini(struct drm_gem_object *obj)
 }
 
 #ifdef CONFIG_DEBUG_FS
+static void describe_fence(struct fence *fence, const char *type,
+		struct seq_file *m)
+{
+	if (!fence_is_signaled(fence))
+		seq_printf(m, "\t%9s: %s %s seq %u\n", type,
+				fence->ops->get_driver_name(fence),
+				fence->ops->get_timeline_name(fence),
+				fence->seqno);
+}
+
 void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 {
-	struct drm_device *dev = obj->dev;
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
+	struct reservation_object *robj = msm_obj->resv;
+	struct reservation_object_list *fobj;
+	struct fence *fence;
 	uint64_t off = drm_vma_node_start(&obj->vma_node);
 
-	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-	seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n",
+	WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+
+	seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu\n",
 			msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
-			msm_obj->read_fence, msm_obj->write_fence,
 			obj->name, obj->refcount.refcount.counter,
 			off, msm_obj->vaddr, obj->size);
+
+	rcu_read_lock();
+	fobj = rcu_dereference(robj->fence);
+	if (fobj) {
+		unsigned int i, shared_count = fobj->shared_count;
+
+		for (i = 0; i < shared_count; i++) {
+			fence = rcu_dereference(fobj->shared[i]);
+			describe_fence(fence, "Shared", m);
+		}
+	}
+
+	fence = rcu_dereference(robj->fence_excl);
+	if (fence)
+		describe_fence(fence, "Exclusive", m);
+	rcu_read_unlock();
 }
 
 void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index b890451..2771d15 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -39,7 +39,6 @@ struct msm_gem_object {
 	 */
 	struct list_head mm_list;
 	struct msm_gpu *gpu;     /* non-null if active */
-	uint32_t read_fence, write_fence;
 
 	/* Transiently in the process of submit ioctl, objects associated
 	 * with the submit are on submit->bo_list.. this only lasts for
@@ -73,19 +72,6 @@ static inline bool is_active(struct msm_gem_object *msm_obj)
 	return msm_obj->gpu != NULL;
 }
 
-static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
-		uint32_t op)
-{
-	uint32_t fence = 0;
-
-	if (op & MSM_PREP_READ)
-		fence = msm_obj->write_fence;
-	if (op & MSM_PREP_WRITE)
-		fence = max(fence, msm_obj->read_fence);
-
-	return fence;
-}
-
 #define MAX_CMDS 4
 
 /* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
@@ -99,7 +85,7 @@ struct msm_gem_submit {
 	struct list_head node;   /* node in gpu submit_list */
 	struct list_head bo_list;
 	struct ww_acquire_ctx ticket;
-	uint32_t fence;
+	struct fence *fence;
 	bool valid;         /* true if no cmdstream patching needed */
 	unsigned int nr_cmds;
 	unsigned int nr_bos;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index b231544..2661a7c 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -184,6 +184,22 @@ fail:
 	return ret;
 }
 
+static int submit_fence_sync(struct msm_gem_submit *submit)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE;
+
+		ret = msm_gem_sync_object(&msm_obj->base, submit->gpu->fctx, write);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
 static int submit_pin_objects(struct msm_gem_submit *submit)
 {
 	int i, ret = 0;
@@ -358,6 +374,10 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 	if (ret)
 		goto out;
 
+	ret = submit_fence_sync(submit);
+	if (ret)
+		goto out;
+
 	ret = submit_pin_objects(submit);
 	if (ret)
 		goto out;
@@ -424,7 +444,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 
 	ret = msm_gpu_submit(gpu, submit, ctx);
 
-	args->fence = submit->fence;
+	args->fence = submit->fence->seqno;
 
 out:
 	submit_cleanup(submit, !!ret);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index e04bd2f..5db4b57 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -266,22 +266,24 @@ static void inactive_start(struct msm_gpu *gpu)
  * Hangcheck detection for locked gpu:
  */
 
-static void retire_submits(struct msm_gpu *gpu, uint32_t fence);
+static void retire_submits(struct msm_gpu *gpu);
 
 static void recover_worker(struct work_struct *work)
 {
 	struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);
 	struct drm_device *dev = gpu->dev;
+	uint32_t fence = gpu->funcs->last_fence(gpu);
 
 	dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
 
+	msm_update_fence(gpu->fctx, fence + 1);
+
 	mutex_lock(&dev->struct_mutex);
 	if (msm_gpu_active(gpu)) {
 		struct msm_gem_submit *submit;
-		uint32_t fence = gpu->funcs->last_fence(gpu);
 
 		/* retire completed submits, plus the one that hung: */
-		retire_submits(gpu, fence + 1);
+		retire_submits(gpu);
 
 		inactive_cancel(gpu);
 		gpu->funcs->recover(gpu);
@@ -444,11 +446,12 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 		drm_gem_object_unreference(&msm_obj->base);
 	}
 
+	fence_put(submit->fence);
 	list_del(&submit->node);
 	kfree(submit);
 }
 
-static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
+static void retire_submits(struct msm_gpu *gpu)
 {
 	struct drm_device *dev = gpu->dev;
 
@@ -460,7 +463,7 @@ static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
 		submit = list_first_entry(&gpu->submit_list,
 				struct msm_gem_submit, node);
 
-		if (submit->fence <= fence) {
+		if (fence_is_signaled(submit->fence)) {
 			retire_submit(gpu, submit);
 		} else {
 			break;
@@ -477,7 +480,7 @@ static void retire_worker(struct work_struct *work)
 	msm_update_fence(gpu->fctx, fence);
 
 	mutex_lock(&dev->struct_mutex);
-	retire_submits(gpu, fence);
+	retire_submits(gpu);
 	mutex_unlock(&dev->struct_mutex);
 
 	if (!msm_gpu_active(gpu))
@@ -502,7 +505,12 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	submit->fence = ++gpu->fctx->last_fence;
+	submit->fence = msm_fence_alloc(gpu->fctx);
+	if (IS_ERR(submit->fence)) {
+		ret = PTR_ERR(submit->fence);
+		submit->fence = NULL;
+		return ret;
+	}
 
 	inactive_cancel(gpu);
 
@@ -526,11 +534,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 		msm_gem_get_iova_locked(&msm_obj->base,
 				submit->gpu->id, &iova);
 
-		if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
-			msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
-
 		if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
 			msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
+		else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
+			msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
 	}
 
 	ret = gpu->funcs->submit(gpu, submit, ctx);
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 9a78c48..b48f73a 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -296,7 +296,7 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit)
 
 	n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
 			TASK_COMM_LEN, current->comm, task_pid_nr(current),
-			submit->fence);
+			submit->fence->seqno);
 
 	rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 02/11] drm/atomic: export drm_atomic_helper_wait_for_fences()
  2016-03-18 23:14 ` [PATCH 02/11] drm/atomic: export drm_atomic_helper_wait_for_fences() Rob Clark
@ 2016-03-30 20:51   ` Gustavo Padovan
  2016-03-31  5:57     ` Daniel Vetter
  0 siblings, 1 reply; 18+ messages in thread
From: Gustavo Padovan @ 2016-03-30 20:51 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel, maarten.lankhorst, linux-arm-msm, freedreno

2016-03-18 Rob Clark <robdclark@gmail.com>:

Hi Rob,

> Signed-off-by: Rob Clark <robdclark@gmail.com>
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 15 +++++++++++++--
>  include/drm/drm_atomic_helper.h     |  2 ++
>  2 files changed, 15 insertions(+), 2 deletions(-)

Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

	Gustavo

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 02/11] drm/atomic: export drm_atomic_helper_wait_for_fences()
  2016-03-30 20:51   ` Gustavo Padovan
@ 2016-03-31  5:57     ` Daniel Vetter
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2016-03-31  5:57 UTC (permalink / raw)
  To: Gustavo Padovan, Rob Clark, dri-devel, maarten.lankhorst,
	linux-arm-msm, freedreno

On Wed, Mar 30, 2016 at 05:51:45PM -0300, Gustavo Padovan wrote:
> 2016-03-18 Rob Clark <robdclark@gmail.com>:
> 
> Hi Rob,
> 
> > Signed-off-by: Rob Clark <robdclark@gmail.com>
> > ---
> >  drivers/gpu/drm/drm_atomic_helper.c | 15 +++++++++++++--
> >  include/drm/drm_atomic_helper.h     |  2 ++
> >  2 files changed, 15 insertions(+), 2 deletions(-)
> 
> Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Applied to drm-misc, thanks.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked()
  2016-03-18 23:14 ` [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked() Rob Clark
@ 2016-03-31 20:23   ` Rob Clark
  2016-04-04  9:02     ` Maarten Lankhorst
  0 siblings, 1 reply; 18+ messages in thread
From: Rob Clark @ 2016-03-31 20:23 UTC (permalink / raw)
  To: dri-devel

In the atomic modesetting path, each driver simply wants to grab a ref
to the exclusive fence from a reservation object to store in the incoming
drm_plane_state, without doing the whole RCU dance.  Since each driver
will need to do this, lets make a helper.

v2: rename to _rcu instead of _unlocked to be more consistent

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
Note that danvet also suggested addition of headerdoc.  But it was a
trap!  In the process I discovered that some files were missing from
the DocBook tmpl, some fixup needed, and complete lack of reservation
related headerdoc.

So the patchset to fixup all that will follow in a few minutes.  But
danvet's punishment for tricking me into fixing that all up is that
the headerdoc he wants applies on top of the patch that I want ;-)

 include/linux/reservation.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index 5a0b64c..49d0576 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -120,6 +120,24 @@ reservation_object_get_excl(struct reservation_object *obj)
 					 reservation_object_held(obj));
 }
 
+static inline struct fence *
+reservation_object_get_excl_rcu(struct reservation_object *obj)
+{
+	struct fence *fence;
+	unsigned seq;
+retry:
+	seq = read_seqcount_begin(&obj->seq);
+	rcu_read_lock();
+	fence = rcu_dereference(obj->fence_excl);
+	if (read_seqcount_retry(&obj->seq, seq)) {
+		rcu_read_unlock();
+		goto retry;
+	}
+	fence = fence_get(fence);
+	rcu_read_unlock();
+	return fence;
+}
+
 int reservation_object_reserve_shared(struct reservation_object *obj);
 void reservation_object_add_shared_fence(struct reservation_object *obj,
 					 struct fence *fence);
-- 
2.5.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked()
  2016-03-31 20:23   ` Rob Clark
@ 2016-04-04  9:02     ` Maarten Lankhorst
  2016-04-04 18:11       ` Rob Clark
  0 siblings, 1 reply; 18+ messages in thread
From: Maarten Lankhorst @ 2016-04-04  9:02 UTC (permalink / raw)
  To: Rob Clark, dri-devel

Op 31-03-16 om 22:23 schreef Rob Clark:
> In the atomic modesetting path, each driver simply wants to grab a ref
> to the exclusive fence from a reservation object to store in the incoming
> drm_plane_state, without doing the whole RCU dance.  Since each driver
> will need to do this, lets make a helper.
>
> v2: rename to _rcu instead of _unlocked to be more consistent
>
Forgot to update commit message. :)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked()
  2016-04-04  9:02     ` Maarten Lankhorst
@ 2016-04-04 18:11       ` Rob Clark
  2016-04-05 10:54         ` Sumit Semwal
  0 siblings, 1 reply; 18+ messages in thread
From: Rob Clark @ 2016-04-04 18:11 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: dri-devel

On Mon, Apr 4, 2016 at 5:02 AM, Maarten Lankhorst
<maarten.lankhorst@linux.intel.com> wrote:
> Op 31-03-16 om 22:23 schreef Rob Clark:
>> In the atomic modesetting path, each driver simply wants to grab a ref
>> to the exclusive fence from a reservation object to store in the incoming
>> drm_plane_state, without doing the whole RCU dance.  Since each driver
>> will need to do this, lets make a helper.
>>
>> v2: rename to _rcu instead of _unlocked to be more consistent
>>
> Forgot to update commit message. :)

oh, whoops.. Sumit, want me to resend or can you just fixup the commit
msg when you apply the patch?

BR,
-R
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked()
  2016-04-04 18:11       ` Rob Clark
@ 2016-04-05 10:54         ` Sumit Semwal
  0 siblings, 0 replies; 18+ messages in thread
From: Sumit Semwal @ 2016-04-05 10:54 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

On 4 April 2016 at 23:41, Rob Clark <robdclark@gmail.com> wrote:
> On Mon, Apr 4, 2016 at 5:02 AM, Maarten Lankhorst
> <maarten.lankhorst@linux.intel.com> wrote:
>> Op 31-03-16 om 22:23 schreef Rob Clark:
>>> In the atomic modesetting path, each driver simply wants to grab a ref
>>> to the exclusive fence from a reservation object to store in the incoming
>>> drm_plane_state, without doing the whole RCU dance.  Since each driver
>>> will need to do this, lets make a helper.
>>>
>>> v2: rename to _rcu instead of _unlocked to be more consistent
>>>
>> Forgot to update commit message. :)
>
> oh, whoops.. Sumit, want me to resend or can you just fixup the commit
> msg when you apply the patch?
>

No worries Rob, I can take care while applying.
> BR,
> -R



-- 
Thanks and regards,

Sumit Semwal
Linaro Mobile Group - Kernel Team Lead
Linaro.org │ Open source software for ARM SoCs
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-04-05 10:54 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-18 23:14 [PATCH 00/11] drm/msm: fencification Rob Clark
2016-03-18 23:14 ` [PATCH 01/11] reservation: add reservation_object_get_excl_unlocked() Rob Clark
2016-03-31 20:23   ` Rob Clark
2016-04-04  9:02     ` Maarten Lankhorst
2016-04-04 18:11       ` Rob Clark
2016-04-05 10:54         ` Sumit Semwal
2016-03-18 23:14 ` [PATCH 02/11] drm/atomic: export drm_atomic_helper_wait_for_fences() Rob Clark
2016-03-30 20:51   ` Gustavo Padovan
2016-03-31  5:57     ` Daniel Vetter
2016-03-18 23:14 ` [PATCH 03/11] drm/msm: move debugfs code to it's own file Rob Clark
2016-03-18 23:14 ` [PATCH 04/11] drm/msm: move fence " Rob Clark
2016-03-18 23:14 ` [PATCH 05/11] drm/msm: use imported dmabuf's reservation object Rob Clark
2016-03-18 23:14 ` [PATCH 06/11] drm/msm: split out timeout_to_jiffies helper Rob Clark
2016-03-18 23:15 ` [PATCH 07/11] drm/msm/gpu: simplify tracking in-flight bo's Rob Clark
2016-03-18 23:15 ` [PATCH 08/11] drm/msm: split locking and pinning BO's Rob Clark
2016-03-18 23:15 ` [PATCH 09/11] drm/msm: introduce msm_fence_context Rob Clark
2016-03-18 23:15 ` [PATCH 10/11] drm/msm: remove fence_cbs Rob Clark
2016-03-18 23:15 ` [PATCH 11/11] drm/msm: 'struct fence' conversion Rob Clark

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.