[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

libdrm: Changes to 'upstream-unstable'



 Android.common.mk                  |    1 
 amdgpu/Android.mk                  |    3 
 amdgpu/Makefile.am                 |    5 
 amdgpu/amdgpu-symbol-check         |    3 
 amdgpu/amdgpu.h                    |   43 +++++
 amdgpu/amdgpu_asic_id.c            |  139 ++++------------
 amdgpu/amdgpu_cs.c                 |   28 +++
 amdgpu/amdgpu_device.c             |   51 +-----
 amdgpu/amdgpu_internal.h           |   18 --
 amdgpu/amdgpu_vamgr.c              |   31 +--
 configure.ac                       |    2 
 data/amdgpu.ids                    |   31 +++
 etnaviv/Makefile.sources           |    1 
 etnaviv/etnaviv-symbol-check       |    5 
 etnaviv/etnaviv_bo_cache.c         |   26 ++-
 etnaviv/etnaviv_cmd_stream.c       |   20 ++
 etnaviv/etnaviv_drm.h              |   43 ++++-
 etnaviv/etnaviv_drmif.h            |   23 ++
 etnaviv/etnaviv_perfmon.c          |  189 ++++++++++++++++++++++
 etnaviv/etnaviv_priv.h             |   25 ++
 exynos/exynos_fimg2d.c             |   21 ++
 exynos/exynos_fimg2d.h             |   21 ++
 exynos/fimg2d_reg.h                |   21 ++
 freedreno/freedreno-symbol-check   |    1 
 freedreno/freedreno_drmif.h        |    3 
 freedreno/freedreno_pipe.c         |   19 ++
 freedreno/freedreno_priv.h         |    3 
 freedreno/kgsl/kgsl_pipe.c         |    3 
 freedreno/kgsl/kgsl_priv.h         |    2 
 freedreno/msm/msm_drm.h            |   40 ++++
 freedreno/msm/msm_pipe.c           |   41 ++++
 freedreno/msm/msm_priv.h           |    3 
 freedreno/msm/msm_ringbuffer.c     |    1 
 include/drm/README                 |   22 --
 include/drm/mga_drm.h              |   12 +
 include/drm/nouveau_drm.h          |   94 ++++++-----
 include/drm/qxl_drm.h              |   82 +++++----
 include/drm/r128_drm.h             |   10 +
 include/drm/radeon_drm.h           |  128 +++++++--------
 include/drm/savage_drm.h           |   20 +-
 include/drm/sis_drm.h              |   10 +
 include/drm/tegra_drm.h            |   14 +
 include/drm/vc4_drm.h              |   47 +++++
 include/drm/via_drm.h              |    8 
 include/drm/vmwgfx_drm.h           |    9 +
 libkms/exynos.c                    |   22 ++
 tests/amdgpu/amdgpu_test.c         |  186 +++++++++++++++++++---
 tests/amdgpu/amdgpu_test.h         |   56 ++++++
 tests/amdgpu/basic_tests.c         |  311 +++++++++++++++++++++++++++++++------
 tests/amdgpu/bo_tests.c            |   75 ++++++++
 tests/amdgpu/cs_tests.c            |   64 +++----
 tests/amdgpu/deadlock_tests.c      |   27 ++-
 tests/amdgpu/uvd_enc_tests.c       |   81 +++------
 tests/amdgpu/vce_tests.c           |   65 +++----
 tests/amdgpu/vcn_tests.c           |   74 +++-----
 tests/exynos/exynos_fimg2d_event.c |   27 ++-
 tests/exynos/exynos_fimg2d_perf.c  |   27 ++-
 tests/exynos/exynos_fimg2d_test.c  |   21 ++
 xf86drm.c                          |   63 +++++++
 xf86drm.h                          |   14 +
 xf86drmMode.c                      |   98 +++++++++++
 xf86drmMode.h                      |   22 ++
 62 files changed, 1907 insertions(+), 648 deletions(-)

New commits:
commit 831036a6f62005da9fb4a75fe043bd96ce672d27
Author: Dave Airlie <airlied@redhat.com>
Date:   Mon Dec 18 11:24:34 2017 +1000

    configure.ac: bump version for release

diff --git a/configure.ac b/configure.ac
index b2d961b..35378b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
 
 AC_PREREQ([2.63])
 AC_INIT([libdrm],
-        [2.4.88],
+        [2.4.89],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
         [libdrm])
 

commit d4331dda5b5969922c4f1e3ad6d53f23becb91ab
Author: Keith Packard <keithp@keithp.com>
Date:   Sat Jul 1 00:43:15 2017 -0700

    drm: Add CrtcGetSequence and CrtcQueueSequence IOCTLs [v2]
    
    These provide a crtc-id based interface to get the current sequence
    (frame) number and to queue an event to be delivered at a specific sequence.
    
    v2: Remove FIRST_PIXEL_OUT flag. This has been removed from the
        proposed kernel API
    
    Signed-off-by: Keith Packard <keithp@keithp.com>
    Signed-off-by: Dave Airlie <airlied@redhat.com>

diff --git a/xf86drm.c b/xf86drm.c
index deb76e4..74b4e23 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -1695,6 +1695,43 @@ int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
     return 0;
 }
 
+int drmCrtcGetSequence(int fd, uint32_t crtcId, uint64_t *sequence, uint64_t *ns)
+{
+    struct drm_crtc_get_sequence get_seq;
+    int ret;
+
+    memclear(get_seq);
+    get_seq.crtc_id = crtcId;
+    ret = drmIoctl(fd, DRM_IOCTL_CRTC_GET_SEQUENCE, &get_seq);
+    if (ret)
+        return ret;
+
+    if (sequence)
+        *sequence = get_seq.sequence;
+    if (ns)
+        *ns = get_seq.sequence_ns;
+    return 0;
+}
+
+int drmCrtcQueueSequence(int fd, uint32_t crtcId, uint32_t flags, uint64_t sequence,
+                         uint64_t *sequence_queued, uint64_t user_data)
+{
+    struct drm_crtc_queue_sequence queue_seq;
+    int ret;
+
+    memclear(queue_seq);
+    queue_seq.crtc_id = crtcId;
+    queue_seq.flags = flags;
+    queue_seq.sequence = sequence;
+    queue_seq.user_data = user_data;
+
+    ret = drmIoctl(fd, DRM_IOCTL_CRTC_QUEUE_SEQUENCE, &queue_seq);
+    if (ret == 0 && sequence_queued)
+        *sequence_queued = queue_seq.sequence;
+
+    return ret;
+}
+
 /**
  * Acquire the AGP device.
  *
diff --git a/xf86drm.h b/xf86drm.h
index 0dbf494..7773d71 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -636,6 +636,12 @@ extern int           drmCtlUninstHandler(int fd);
 extern int           drmSetClientCap(int fd, uint64_t capability,
 				     uint64_t value);
 
+extern int           drmCrtcGetSequence(int fd, uint32_t crtcId,
+					uint64_t *sequence, uint64_t *ns);
+extern int           drmCrtcQueueSequence(int fd, uint32_t crtcId,
+					  uint32_t flags, uint64_t sequence,
+					  uint64_t *sequence_queued,
+					  uint64_t user_data);
 /* General user-level programmer's API: authenticated client and/or X */
 extern int           drmMap(int fd,
 			    drm_handle_t handle,
@@ -728,7 +734,7 @@ extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2);
 extern int drmSetMaster(int fd);
 extern int drmDropMaster(int fd);
 
-#define DRM_EVENT_CONTEXT_VERSION 3
+#define DRM_EVENT_CONTEXT_VERSION 4
 
 typedef struct _drmEventContext {
 
@@ -755,6 +761,10 @@ typedef struct _drmEventContext {
 				   unsigned int crtc_id,
 				   void *user_data);
 
+	void (*sequence_handler)(int fd,
+				 uint64_t sequence,
+				 uint64_t ns,
+				 uint64_t user_data);
 } drmEventContext, *drmEventContextPtr;
 
 extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
diff --git a/xf86drmMode.c b/xf86drmMode.c
index eddad8c..15957ff 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -889,6 +889,7 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
 	int len, i;
 	struct drm_event *e;
 	struct drm_event_vblank *vblank;
+	struct drm_event_crtc_sequence *seq;
 	void *user_data;
 
 	/* The DRM read semantics guarantees that we always get only
@@ -933,6 +934,14 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
 							 vblank->tv_usec,
 							 user_data);
 			break;
+		case DRM_EVENT_CRTC_SEQUENCE:
+			seq = (struct drm_event_crtc_sequence *) e;
+			if (evctx->version >= 4 && evctx->sequence_handler)
+				evctx->sequence_handler(fd,
+							seq->sequence,
+							seq->time_ns,
+							seq->user_data);
+			break;
 		default:
 			break;
 		}

commit c4171535389d72e9135c9615cecd07b346fd6d7e
Author: Keith Packard <keithp@keithp.com>
Date:   Thu Mar 16 18:11:05 2017 -0700

    drm: Add drm mode lease ioctl wrappers [v3]
    
    drmModeCreateLease
    drmModeListLessees
    drmModeGetLease
    drmModeRevokeLease
    
    Changes for v2:
    
    Remove lessee id from GetLease
    Remove lessor_id from ListLeases
    Add revoke
    Renumber to track kernel rebase on drm-next
    
    Signed-off-by: Keith Packard <keithp@keithp.com>
    Signed-off-by: Dave Airlie <airlied@redhat.com>

diff --git a/xf86drmMode.c b/xf86drmMode.c
index 2b3887b..eddad8c 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1485,3 +1485,92 @@ drmModeDestroyPropertyBlob(int fd, uint32_t id)
 	destroy.blob_id = id;
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy);
 }
+
+int
+drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id)
+{
+	struct drm_mode_create_lease create;
+	int ret;
+
+	memclear(create);
+	create.object_ids = (uintptr_t) objects;
+	create.object_count = num_objects;
+	create.flags = flags;
+
+	ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATE_LEASE, &create);
+	if (ret == 0) {
+		*lessee_id = create.lessee_id;
+		return create.fd;
+	}
+	return -errno;
+}
+
+drmModeLesseeListPtr
+drmModeListLessees(int fd)
+{
+	struct drm_mode_list_lessees list;
+	uint32_t count;
+	drmModeLesseeListPtr ret;
+
+	memclear(list);
+
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list))
+		return NULL;
+
+	count = list.count_lessees;
+	ret = drmMalloc(sizeof (drmModeLesseeListRes) + count * sizeof (ret->lessees[0]));
+	if (!ret)
+		return NULL;
+
+	list.lessees_ptr = VOID2U64(&ret->lessees[0]);
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) {
+		drmFree(ret);
+		return NULL;
+	}
+
+	ret->count = count;
+	return ret;
+}
+
+drmModeObjectListPtr
+drmModeGetLease(int fd)
+{
+	struct drm_mode_get_lease get;
+	uint32_t count;
+	drmModeObjectListPtr ret;
+
+	memclear(get);
+
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get))
+		return NULL;
+
+	count = get.count_objects;
+	ret = drmMalloc(sizeof (drmModeObjectListRes) + count * sizeof (ret->objects[0]));
+	if (!ret)
+		return NULL;
+
+	get.objects_ptr = VOID2U64(&ret->objects[0]);
+	if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) {
+		drmFree(ret);
+		return NULL;
+	}
+
+	ret->count = count;
+	return ret;
+}
+
+int
+drmModeRevokeLease(int fd, uint32_t lessee_id)
+{
+	struct drm_mode_revoke_lease revoke;
+	int ret;
+
+	memclear(revoke);
+
+	revoke.lessee_id = lessee_id;
+
+	ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_REVOKE_LEASE, &revoke);
+	if (ret == 0)
+		return 0;
+	return -errno;
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 6dbe335..3cd27ae 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -521,6 +521,28 @@ extern int drmModeCreatePropertyBlob(int fd, const void *data, size_t size,
 				     uint32_t *id);
 extern int drmModeDestroyPropertyBlob(int fd, uint32_t id);
 
+/*
+ * DRM mode lease APIs. These create and manage new drm_masters with
+ * access to a subset of the available DRM resources
+ */
+
+extern int drmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, uint32_t *lessee_id);
+
+typedef struct drmModeLesseeList {
+	uint32_t count;
+	uint32_t lessees[0];
+} drmModeLesseeListRes, *drmModeLesseeListPtr;
+
+extern drmModeLesseeListPtr drmModeListLessees(int fd);
+
+typedef struct drmModeObjectList {
+	uint32_t count;
+	uint32_t objects[0];
+} drmModeObjectListRes, *drmModeObjectListPtr;
+
+extern drmModeObjectListPtr drmModeGetLease(int fd);
+
+extern int drmModeRevokeLease(int fd, uint32_t lessee_id);
 
 #if defined(__cplusplus)
 }

commit 5889f6ba1a250777ff8b6ba96a35dba3f02071ff
Author: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Date:   Sun Dec 17 00:27:10 2017 +0100

    amdgpu: Add syncobj reset & signal wrappers.
    
    Signed-off-by: Dave Airlie <airlied@redhat.com>

diff --git a/amdgpu/amdgpu-symbol-check b/amdgpu/amdgpu-symbol-check
index 59db3cf..3f298d1 100755
--- a/amdgpu/amdgpu-symbol-check
+++ b/amdgpu/amdgpu-symbol-check
@@ -45,6 +45,8 @@ amdgpu_cs_submit
 amdgpu_cs_submit_raw
 amdgpu_cs_syncobj_export_sync_file
 amdgpu_cs_syncobj_import_sync_file
+amdgpu_cs_syncobj_reset
+amdgpu_cs_syncobj_signal
 amdgpu_cs_syncobj_wait
 amdgpu_cs_wait_fences
 amdgpu_cs_wait_semaphore
diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h
index c95cb03..2eb03bf 100644
--- a/amdgpu/amdgpu.h
+++ b/amdgpu/amdgpu.h
@@ -1382,6 +1382,34 @@ int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev,
 			      uint32_t syncobj);
 
 /**
+ * Reset kernel sync objects to unsignalled state.
+ *
+ * \param dev           - \c [in] device handle
+ * \param syncobjs      - \c [in] array of sync object handles
+ * \param syncobj_count - \c [in] number of handles in syncobjs
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_cs_syncobj_reset(amdgpu_device_handle dev,
+			    const uint32_t *syncobjs, uint32_t syncobj_count);
+
+/**
+ * Signal kernel sync objects.
+ *
+ * \param dev           - \c [in] device handle
+ * \param syncobjs      - \c [in] array of sync object handles
+ * \param syncobj_count - \c [in] number of handles in syncobjs
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_cs_syncobj_signal(amdgpu_device_handle dev,
+			     const uint32_t *syncobjs, uint32_t syncobj_count);
+
+/**
  *  Wait for one or all sync objects to signal.
  *
  * \param   dev	    - \c [in] self-explanatory
diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c
index 9e157a8..987daa4 100644
--- a/amdgpu/amdgpu_cs.c
+++ b/amdgpu/amdgpu_cs.c
@@ -634,6 +634,24 @@ int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev,
 	return drmSyncobjDestroy(dev->fd, handle);
 }
 
+int amdgpu_cs_syncobj_reset(amdgpu_device_handle dev,
+			    const uint32_t *syncobjs, uint32_t syncobj_count)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjReset(dev->fd, syncobjs, syncobj_count);
+}
+
+int amdgpu_cs_syncobj_signal(amdgpu_device_handle dev,
+			     const uint32_t *syncobjs, uint32_t syncobj_count)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjSignal(dev->fd, syncobjs, syncobj_count);
+}
+
 int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev,
 			   uint32_t *handles, unsigned num_handles,
 			   int64_t timeout_nsec, unsigned flags,

commit 1abccedc4d18305e8c3e3dd00d3262c134ef1d44
Author: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Date:   Sun Dec 17 00:27:09 2017 +0100

    drm: Add drmSyncobjReset & drmSyncobjSignal wrappers.
    
    anv already uses the ioctls but does not use libdrm, so these were
    not wrapped yet.
    
    Signed-off-by: Dave Airlie <airlied@redhat.com>

diff --git a/xf86drm.c b/xf86drm.c
index c44621c..deb76e4 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -4247,3 +4247,29 @@ int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles,
         *first_signaled = args.first_signaled;
     return ret;
 }
+
+int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count)
+{
+    struct drm_syncobj_array args;
+    int ret;
+
+    memclear(args);
+    args.handles = (uintptr_t)handles;
+    args.count_handles = handle_count;
+
+    ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &args);
+    return ret;
+}
+
+int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count)
+{
+    struct drm_syncobj_array args;
+    int ret;
+
+    memclear(args);
+    args.handles = (uintptr_t)handles;
+    args.count_handles = handle_count;
+
+    ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &args);
+    return ret;
+}
diff --git a/xf86drm.h b/xf86drm.h
index ea650ef..0dbf494 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -863,6 +863,8 @@ extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd);
 extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles,
 			  int64_t timeout_nsec, unsigned flags,
 			  uint32_t *first_signaled);
+extern int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count);
+extern int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count);
 
 #if defined(__cplusplus)
 }

commit 7d984e609470aa38d4c3f7d48e26fa763a03af13
Author: Lucas Stach <l.stach@pengutronix.de>
Date:   Fri Dec 15 11:30:26 2017 +0100

    etnaviv: fix BO cache to properly work with different flags
    
    Currently if the oldest BO in a bucket has different flags than what we
    look for we'll miss the cache.Fix this by iterating over the cached BOs
    until we find the oldest one with matching flags. This improves the hit
    ratio for some of the buckets.
    
    Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
    Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
    Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>

diff --git a/etnaviv/etnaviv_bo_cache.c b/etnaviv/etnaviv_bo_cache.c
index 8924651..6208230 100644
--- a/etnaviv/etnaviv_bo_cache.c
+++ b/etnaviv/etnaviv_bo_cache.c
@@ -124,20 +124,32 @@ static int is_idle(struct etna_bo *bo)
 
 static struct etna_bo *find_in_bucket(struct etna_bo_bucket *bucket, uint32_t flags)
 {
-	struct etna_bo *bo = NULL;
+	struct etna_bo *bo = NULL, *tmp;
 
 	pthread_mutex_lock(&table_lock);
-	while (!LIST_IS_EMPTY(&bucket->list)) {
-		bo = LIST_ENTRY(struct etna_bo, bucket->list.next, list);
 
-		if (bo->flags == flags && is_idle(bo)) {
-			list_del(&bo->list);
-			break;
+	if (LIST_IS_EMPTY(&bucket->list))
+		goto out_unlock;
+
+	LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bucket->list, list) {
+		/* skip BOs with different flags */
+		if (bo->flags != flags)
+			continue;
+
+		/* check if the first BO with matching flags is idle */
+		if (is_idle(bo)) {
+			list_delinit(&bo->list);
+			goto out_unlock;
 		}
 
-		bo = NULL;
+		/* If the oldest BO is still busy, don't try younger ones */
 		break;
 	}
+
+	/* There was no matching buffer found */
+	bo = NULL;
+
+out_unlock:
 	pthread_mutex_unlock(&table_lock);
 
 	return bo;

commit 4f8e426884a51b6786459ea2505f1ce82a13a87c
Author: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Date:   Fri Dec 15 13:21:02 2017 -0500

    tests/amdgpu: Add return CUE_SUCCESS to suite_vcn_tests_clean.
    
        fixes: 806d0803600000faecb4025d8e9c7490cb097c25 (amdgpu: Use new suite/test disabling functionality.)
        bug: https://bugs.freedesktop.org/show_bug.cgi?id=104280
    
    Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
    Reviewed-by: Christian König <christian.koenig@amd.com>

diff --git a/tests/amdgpu/vcn_tests.c b/tests/amdgpu/vcn_tests.c
index 53a2d08..9224bc3 100644
--- a/tests/amdgpu/vcn_tests.c
+++ b/tests/amdgpu/vcn_tests.c
@@ -144,6 +144,8 @@ int suite_vcn_tests_clean(void)
 	r = amdgpu_device_deinitialize(device_handle);
 	if (r)
 		return CUE_SCLEAN_FAILED;
+
+	return CUE_SUCCESS;
 }
 
 static int submit(unsigned ndw, unsigned ip)

commit 6a6b7432bfe94f8047b688fd6875ad93d153c6d0
Author: Christian Gmeiner <christian.gmeiner@gmail.com>
Date:   Fri Dec 15 08:43:40 2017 +0100

    etnaviv: support performance monitor requests
    
    Add etna_cmd_stream_perf(..) to submit perform requests.
    Userspace can submit pmrs via submit ioctl to sample perfmon
    signals.
    
    v3:
     - mark perfmon bos as RW
    
    Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
    Reviewed-by: Lucas Stach <l.stach@pengutronix.de>

diff --git a/etnaviv/etnaviv-symbol-check b/etnaviv/etnaviv-symbol-check
index bd95b45..bc50961 100755
--- a/etnaviv/etnaviv-symbol-check
+++ b/etnaviv/etnaviv-symbol-check
@@ -41,6 +41,7 @@ etna_cmd_stream_timestamp
 etna_cmd_stream_flush
 etna_cmd_stream_flush2
 etna_cmd_stream_finish
+etna_cmd_stream_perf
 etna_cmd_stream_reloc
 etna_perfmon_create
 etna_perfmon_del
diff --git a/etnaviv/etnaviv_cmd_stream.c b/etnaviv/etnaviv_cmd_stream.c
index 8d0e813..e8c58cd 100644
--- a/etnaviv/etnaviv_cmd_stream.c
+++ b/etnaviv/etnaviv_cmd_stream.c
@@ -105,6 +105,7 @@ void etna_cmd_stream_del(struct etna_cmd_stream *stream)
 
 	free(stream->buffer);
 	free(priv->submit.relocs);
+	free(priv->submit.pmrs);
 	free(priv);
 }
 
@@ -115,6 +116,7 @@ static void reset_buffer(struct etna_cmd_stream *stream)
 	stream->offset = 0;
 	priv->submit.nr_bos = 0;
 	priv->submit.nr_relocs = 0;
+	priv->submit.nr_pmrs = 0;
 	priv->nr_bos = 0;
 
 	if (priv->reset_notify)
@@ -191,6 +193,8 @@ static void flush(struct etna_cmd_stream *stream, int in_fence_fd,
 		.nr_bos = priv->submit.nr_bos,
 		.relocs = VOID2U64(priv->submit.relocs),
 		.nr_relocs = priv->submit.nr_relocs,
+		.pmrs = VOID2U64(priv->submit.pmrs),
+		.nr_pmrs = priv->submit.nr_pmrs,
 		.stream = VOID2U64(stream->buffer),
 		.stream_size = stream->offset * 4, /* in bytes */
 	};
@@ -260,3 +264,19 @@ void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_rel
 
 	etna_cmd_stream_emit(stream, addr);
 }
+
+void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p)
+{
+	struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
+	struct drm_etnaviv_gem_submit_pmr *pmr;
+	uint32_t idx = APPEND(&priv->submit, pmrs);
+
+	pmr = &priv->submit.pmrs[idx];
+
+	pmr->flags = p->flags;
+	pmr->sequence = p->sequence;
+	pmr->read_offset = p->offset;
+	pmr->read_idx = bo2idx(stream, p->bo, ETNA_SUBMIT_BO_READ | ETNA_SUBMIT_BO_WRITE);
+	pmr->domain = p->signal->domain->id;
+	pmr->signal = p->signal->signal;
+}
diff --git a/etnaviv/etnaviv_drmif.h b/etnaviv/etnaviv_drmif.h
index 949b9b6..5a6bef8 100644
--- a/etnaviv/etnaviv_drmif.h
+++ b/etnaviv/etnaviv_drmif.h
@@ -201,4 +201,16 @@ void etna_perfmon_del(struct etna_perfmon *perfmon);
 struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name);
 struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name);
 
+struct etna_perf {
+#define ETNA_PM_PROCESS_PRE             0x0001
+#define ETNA_PM_PROCESS_POST            0x0002
+	uint32_t flags;
+	uint32_t sequence;
+	struct etna_perfmon_signal *signal;
+	struct etna_bo *bo;
+	uint32_t offset;
+};
+
+void etna_cmd_stream_perf(struct etna_cmd_stream *stream, const struct etna_perf *p);
+
 #endif /* ETNAVIV_DRMIF_H_ */
diff --git a/etnaviv/etnaviv_priv.h b/etnaviv/etnaviv_priv.h
index 7b289b6..e45d364 100644
--- a/etnaviv/etnaviv_priv.h
+++ b/etnaviv/etnaviv_priv.h
@@ -140,6 +140,10 @@ struct etna_cmd_stream_priv {
 		/* reloc's table: */
 		struct drm_etnaviv_gem_submit_reloc *relocs;
 		uint32_t nr_relocs, max_relocs;
+
+		/* perf's table: */
+		struct drm_etnaviv_gem_submit_pmr *pmrs;
+		uint32_t nr_pmrs, max_pmrs;
 	} submit;
 
 	/* should have matching entries in submit.bos: */

commit 305c1d113ca26cadf695bd41eeed20cff79aa671
Author: Christian Gmeiner <christian.gmeiner@gmail.com>
Date:   Fri Dec 15 08:43:39 2017 +0100

    etnaviv: add permon support
    
    Query all domains and their signals and provide it this information
    via struct etna_perfmon and the corresponding api functions.
    
    v2:
     - code style changes
     - etna_perfmon_create(..): add missing clean up in error case
    
    Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
    Reviewed-by: Lucas Stach <l.stach@pengutronix.de>

diff --git a/etnaviv/Makefile.sources b/etnaviv/Makefile.sources
index 5258056..0eb7378 100644
--- a/etnaviv/Makefile.sources
+++ b/etnaviv/Makefile.sources
@@ -3,6 +3,7 @@ LIBDRM_ETNAVIV_FILES := \
 	etnaviv_gpu.c \
 	etnaviv_bo.c \
 	etnaviv_bo_cache.c \
+	etnaviv_perfmon.c \
 	etnaviv_pipe.c \
 	etnaviv_cmd_stream.c \
 	etnaviv_drm.h \
diff --git a/etnaviv/etnaviv-symbol-check b/etnaviv/etnaviv-symbol-check
index 0e2030e..bd95b45 100755
--- a/etnaviv/etnaviv-symbol-check
+++ b/etnaviv/etnaviv-symbol-check
@@ -42,6 +42,10 @@ etna_cmd_stream_flush
 etna_cmd_stream_flush2
 etna_cmd_stream_finish
 etna_cmd_stream_reloc
+etna_perfmon_create
+etna_perfmon_del
+etna_perfmon_get_dom_by_name
+etna_perfmon_get_sig_by_name
 EOF
 done)
 
diff --git a/etnaviv/etnaviv_drmif.h b/etnaviv/etnaviv_drmif.h
index 87704ac..949b9b6 100644
--- a/etnaviv/etnaviv_drmif.h
+++ b/etnaviv/etnaviv_drmif.h
@@ -35,6 +35,9 @@ struct etna_pipe;
 struct etna_gpu;
 struct etna_device;
 struct etna_cmd_stream;
+struct etna_perfmon;
+struct etna_perfmon_domain;
+struct etna_perfmon_signal;
 
 enum etna_pipe_id {
 	ETNA_PIPE_3D = 0,
@@ -190,4 +193,12 @@ struct etna_reloc {
 
 void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_reloc *r);
 
+/* performance monitoring functions:
+ */
+
+struct etna_perfmon *etna_perfmon_create(struct etna_pipe *pipe);
+void etna_perfmon_del(struct etna_perfmon *perfmon);
+struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name);
+struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name);
+
 #endif /* ETNAVIV_DRMIF_H_ */
diff --git a/etnaviv/etnaviv_perfmon.c b/etnaviv/etnaviv_perfmon.c
new file mode 100644
index 0000000..aa5130a
--- /dev/null
+++ b/etnaviv/etnaviv_perfmon.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2017 Etnaviv Project
+ * Copyright (C) 2017 Zodiac Inflight Innovations
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Christian Gmeiner <christian.gmeiner@gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "etnaviv_priv.h"
+
+static int etna_perfmon_query_signals(struct etna_perfmon *pm, struct etna_perfmon_domain *dom)
+{
+	struct etna_device *dev = pm->pipe->gpu->dev;
+	struct drm_etnaviv_pm_signal req = {
+		.pipe = pm->pipe->id,
+		.domain = dom->id
+	};
+
+	do {
+		struct etna_perfmon_signal *sig;
+		int ret;
+
+		ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_SIG, &req, sizeof(req));
+		if (ret)
+			break;
+
+		sig = calloc(1, sizeof(*sig));
+		if (!sig)
+			return -ENOMEM;
+
+		INFO_MSG("perfmon signal:");
+		INFO_MSG("id         = %d", req.id);
+		INFO_MSG("name       = %s", req.name);
+
+		sig->domain = dom;
+		sig->signal = req.id;
+		strncpy(sig->name, req.name, sizeof(sig->name));
+		list_addtail(&sig->head, &dom->signals);
+	} while (req.iter != 0xffff);
+
+	return 0;
+}
+
+static int etna_perfmon_query_domains(struct etna_perfmon *pm)
+{
+	struct etna_device *dev = pm->pipe->gpu->dev;
+	struct drm_etnaviv_pm_domain req = {
+		.pipe = pm->pipe->id
+	};
+
+	do {
+		struct etna_perfmon_domain *dom;
+		int ret;
+
+		ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_PM_QUERY_DOM, &req, sizeof(req));
+		if (ret)
+			break;
+
+		dom = calloc(1, sizeof(*dom));
+		if (!dom)
+			return -ENOMEM;
+
+		list_inithead(&dom->signals);
+		dom->id = req.id;
+		strncpy(dom->name, req.name, sizeof(dom->name));
+		list_addtail(&dom->head, &pm->domains);
+
+		INFO_MSG("perfmon domain:");
+		INFO_MSG("id         = %d", req.id);
+		INFO_MSG("name       = %s", req.name);
+		INFO_MSG("nr_signals = %d", req.nr_signals);
+
+		/* Query all available signals for this domain. */
+		if (req.nr_signals > 0) {
+			ret = etna_perfmon_query_signals(pm, dom);
+			if (ret)
+				return ret;
+		}
+	} while (req.iter != 0xff);
+
+	return 0;
+}
+
+static void etna_perfmon_free_signals(struct etna_perfmon_domain *dom)
+{
+	struct etna_perfmon_signal *sig, *next;
+
+	LIST_FOR_EACH_ENTRY_SAFE(sig, next, &dom->signals, head) {
+		list_del(&sig->head);
+		free(sig);
+	}
+}
+
+static void etna_perfmon_free_domains(struct etna_perfmon *pm)
+{
+	struct etna_perfmon_domain *dom, *next;
+
+	LIST_FOR_EACH_ENTRY_SAFE(dom, next, &pm->domains, head) {
+		etna_perfmon_free_signals(dom);
+		list_del(&dom->head);
+		free(dom);
+	}
+}
+
+struct etna_perfmon *etna_perfmon_create(struct etna_pipe *pipe)
+{
+	struct etna_perfmon *pm;
+	int ret;
+
+	pm = calloc(1, sizeof(*pm));
+	if (!pm) {
+		ERROR_MSG("allocation failed");
+		return NULL;
+	}
+
+	list_inithead(&pm->domains);
+	pm->pipe = pipe;
+
+	/* query all available domains and sources for this device */
+	ret = etna_perfmon_query_domains(pm);
+	if (ret)
+		goto fail;
+
+	return pm;
+
+fail:
+	etna_perfmon_del(pm);
+	return NULL;
+}
+
+void etna_perfmon_del(struct etna_perfmon *pm)
+{
+	if (!pm)
+		return;
+
+	etna_perfmon_free_domains(pm);
+	free(pm);
+}
+
+struct etna_perfmon_domain *etna_perfmon_get_dom_by_name(struct etna_perfmon *pm, const char *name)
+{
+	struct etna_perfmon_domain *dom;
+
+	if (pm) {
+		LIST_FOR_EACH_ENTRY(dom, &pm->domains, head) {
+			if (!strcmp(dom->name, name))
+				return dom;
+		}
+	}
+
+	return NULL;
+}
+
+struct etna_perfmon_signal *etna_perfmon_get_sig_by_name(struct etna_perfmon_domain *dom, const char *name)
+{
+	struct etna_perfmon_signal *signal;
+
+	if (dom) {
+		LIST_FOR_EACH_ENTRY(signal, &dom->signals, head) {
+			if (!strcmp(signal->name, name))
+				return signal;
+		}
+	}
+
+	return NULL;
+}
diff --git a/etnaviv/etnaviv_priv.h b/etnaviv/etnaviv_priv.h
index 1334ba3..7b289b6 100644
--- a/etnaviv/etnaviv_priv.h
+++ b/etnaviv/etnaviv_priv.h
@@ -151,6 +151,27 @@ struct etna_cmd_stream_priv {
 	void *reset_notify_priv;
 };
 
+struct etna_perfmon {
+	struct list_head domains;
+	struct etna_pipe *pipe;
+};
+
+struct etna_perfmon_domain
+{
+	struct list_head head;
+	struct list_head signals;
+	uint8_t id;
+	char name[64];
+};
+


Reply to: