libdrm: reduce number of reallocations in drmModeAtomicAddProperty
am: c5371788ed

Change-Id: I3815cd86f4bdc41b5c7553e9ca237d8cc8cfd88f
diff --git a/.editorconfig b/.editorconfig
index 893b7be..29b4f39 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -17,3 +17,7 @@
 [*.m4]
 indent_style = space
 indent_size = 2
+
+[{meson.build,meson_options.txt}]
+indent_style = space
+indent_size = 2
diff --git a/Android.bp b/Android.bp
index 429c22c..9121068 100644
--- a/Android.bp
+++ b/Android.bp
@@ -54,7 +54,7 @@
         "libdrm_sources",
     ],
 
-    export_include_dirs: ["include/drm"],
+    export_include_dirs: ["include/drm", "android"],
 
     cflags: [
         "-Wno-enum-conversion",
diff --git a/Makefile.am b/Makefile.am
index 2bf644b..6de5677 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -113,6 +113,7 @@
 	$(TEGRA_SUBDIR) \
 	$(VC4_SUBDIR) \
 	$(ETNAVIV_SUBDIR) \
+	data \
 	tests \
 	$(MAN_SUBDIR) \
 	$(ROCKCHIP_SUBDIR)
@@ -139,7 +140,37 @@
 klibdrminclude_HEADERS += $(LIBDRM_INCLUDE_VMWGFX_H_FILES)
 endif
 
-EXTRA_DIST = include/drm/README
+EXTRA_DIST = \
+	include/drm/README \
+	amdgpu/meson.build \
+	data/meson.build \
+	etnaviv/meson.build \
+	exynos/meson.build \
+	freedreno/meson.build \
+	intel/meson.build \
+	libkms/meson.build \
+	man/meson.build \
+	nouveau/meson.build \
+	omap/meson.build \
+	radeon/meson.build \
+	tegra/meson.build \
+	tests/amdgpu/meson.build \
+	tests/etnaviv/meson.build \
+	tests/exynos/meson.build \
+	tests/kms/meson.build \
+	tests/kmstest/meson.build \
+	tests/meson.build \
+	tests/modeprint/meson.build \
+	tests/modetest/meson.build \
+	tests/nouveau/meson.build \
+	tests/proptest/meson.build \
+	tests/radeon/meson.build \
+	tests/tegra/meson.build \
+	tests/util/meson.build \
+	tests/vbltest/meson.build \
+	vc4/meson.build \
+	meson.build \
+	meson_options.txt
 
 copy-headers :
 	cp -r $(kernel_source)/include/uapi/drm/*.h $(top_srcdir)/include/drm/
diff --git a/Makefile.sources b/Makefile.sources
index 10aa1d0..1f8372b 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -37,5 +37,8 @@
 	include/drm/via_drm.h \
 	include/drm/virtgpu_drm.h
 
+LIBDRM_INCLUDE_ANDROID_H_FILES := \
+	android/gralloc_handle.h
+
 LIBDRM_INCLUDE_VMWGFX_H_FILES := \
 	include/drm/vmwgfx_drm.h
diff --git a/README b/README
index 26cab9d..f3df9ac 100644
--- a/README
+++ b/README
@@ -15,9 +15,27 @@
 Compiling
 ---------
 
-libdrm  is  a  standard  autotools  package and  follows  the  normal
-configure, build  and install steps.   The first step is  to configure
-the package, which is done by running the configure shell script:
+libdrm has two build systems, a legacy autotools build system, and a newer
+meson build system. The meson build system is much faster, and offers a
+slightly different interface, but otherwise provides an equivalent feature set.
+
+To use it:
+
+    meson builddir/
+
+By default this will install into /usr/local, you can change your prefix
+with --prefix=/usr (or `meson configure builddir/ -Dprefix=/usr` after 
+the initial meson setup).
+
+Then use ninja to build and install:
+
+    ninja -C builddir/ install
+
+If you are installing into a system location you will need to run install
+separately, and as root.
+
+
+Alternatively you can invoke autotools configure:
 
 	./configure
 
diff --git a/RELEASING b/RELEASING
index 262ca08..7e03e3b 100644
--- a/RELEASING
+++ b/RELEASING
@@ -9,9 +9,9 @@
 
 Follow these steps to release a new version of libdrm:
 
-  1) Bump the version number in configure.ac. We seem to have settled
-     for 2.4.x as the versioning scheme for libdrm, so just bump the
-     micro version.
+  1) Bump the version number in configure.ac and meson.build. We seem
+     to have settled for 2.4.x as the versioning scheme for libdrm, so
+     just bump the  micro version.
 
   2) Run autoconf and then re-run ./configure so the build system
      picks up the new version number.
diff --git a/amdgpu/.editorconfig b/amdgpu/.editorconfig
new file mode 100644
index 0000000..426273f
--- /dev/null
+++ b/amdgpu/.editorconfig
@@ -0,0 +1,13 @@
+# To use this config with your editor, follow the instructions at:
+# http://editorconfig.org
+
+[*]
+charset = utf-8
+indent_style = tab
+indent_size = 8
+tab_width = 8
+insert_final_newline = true
+
+[meson.build]
+indent_style = space
+indent_size = 2
diff --git a/amdgpu/Android.bp b/amdgpu/Android.bp
index a63b617..976f03e 100644
--- a/amdgpu/Android.bp
+++ b/amdgpu/Android.bp
@@ -2,6 +2,11 @@
 
 cc_library_shared {
     name: "libdrm_amdgpu",
+
+    cflags: [
+	"-DAMDGPU_ASIC_ID_TABLE=\"/vendor/etc/hwdata/amdgpu.ids\""
+    ],
+
     defaults: [
         "libdrm_defaults",
         "libdrm_amdgpu_sources",
diff --git a/amdgpu/Android.sources.bp b/amdgpu/Android.sources.bp
index 62b8f05..ed85682 100644
--- a/amdgpu/Android.sources.bp
+++ b/amdgpu/Android.sources.bp
@@ -3,11 +3,13 @@
 cc_defaults {
     name: "libdrm_amdgpu_sources",
     srcs: [
+	"amdgpu_asic_id.c",
         "amdgpu_bo.c",
         "amdgpu_cs.c",
         "amdgpu_device.c",
         "amdgpu_gpu_info.c",
         "amdgpu_vamgr.c",
+	"amdgpu_vm.c",
         "util_hash.c",
         "util_hash_table.c",
     ],
diff --git a/amdgpu/Makefile.am b/amdgpu/Makefile.am
index cf7bc1b..a1b0d05 100644
--- a/amdgpu/Makefile.am
+++ b/amdgpu/Makefile.am
@@ -30,12 +30,16 @@
 	$(PTHREADSTUBS_CFLAGS) \
 	-I$(top_srcdir)/include/drm
 
+libdrmdatadir = @libdrmdatadir@
+AM_CPPFLAGS = -DAMDGPU_ASIC_ID_TABLE=\"${libdrmdatadir}/amdgpu.ids\"
+
 libdrm_amdgpu_la_LTLIBRARIES = libdrm_amdgpu.la
 libdrm_amdgpu_ladir = $(libdir)
 libdrm_amdgpu_la_LDFLAGS = -version-number 1:0:0 -no-undefined
 libdrm_amdgpu_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
 
 libdrm_amdgpu_la_SOURCES = $(LIBDRM_AMDGPU_FILES)
+amdgpu_asic_id.lo: $(top_srcdir)/data/amdgpu.ids
 
 libdrm_amdgpuincludedir = ${includedir}/libdrm
 libdrm_amdgpuinclude_HEADERS = $(LIBDRM_AMDGPU_H_FILES)
diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources
index 487b9e0..498b64c 100644
--- a/amdgpu/Makefile.sources
+++ b/amdgpu/Makefile.sources
@@ -1,11 +1,12 @@
 LIBDRM_AMDGPU_FILES := \
-	amdgpu_asic_id.h \
+	amdgpu_asic_id.c \
 	amdgpu_bo.c \
 	amdgpu_cs.c \
 	amdgpu_device.c \
 	amdgpu_gpu_info.c \
 	amdgpu_internal.h \
 	amdgpu_vamgr.c \
+	amdgpu_vm.c \
 	util_hash.c \
 	util_hash.h \
 	util_hash_table.c \
diff --git a/amdgpu/amdgpu-symbol-check b/amdgpu/amdgpu-symbol-check
index 87f4fd2..90b7a1d 100755
--- a/amdgpu/amdgpu-symbol-check
+++ b/amdgpu/amdgpu-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.am/libdrm_amdgpuinclude_HEADERS
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_amdgpu.so} | awk '{print $3}' | while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_amdgpu.so} | awk '{print $3}' | while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
@@ -22,16 +22,34 @@
 amdgpu_bo_query_info
 amdgpu_bo_set_metadata
 amdgpu_bo_va_op
+amdgpu_bo_va_op_raw
 amdgpu_bo_wait_for_idle
 amdgpu_create_bo_from_user_mem
+amdgpu_cs_chunk_fence_info_to_data
+amdgpu_cs_chunk_fence_to_dep
 amdgpu_cs_create_semaphore
+amdgpu_cs_create_syncobj
+amdgpu_cs_create_syncobj2
 amdgpu_cs_ctx_create
+amdgpu_cs_ctx_create2
 amdgpu_cs_ctx_free
 amdgpu_cs_destroy_semaphore
+amdgpu_cs_destroy_syncobj
+amdgpu_cs_export_syncobj
+amdgpu_cs_fence_to_handle
+amdgpu_cs_import_syncobj
 amdgpu_cs_query_fence_status
 amdgpu_cs_query_reset_state
+amdgpu_query_sw_info
 amdgpu_cs_signal_semaphore
 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
 amdgpu_device_deinitialize
 amdgpu_device_initialize
@@ -45,10 +63,13 @@
 amdgpu_query_hw_ip_count
 amdgpu_query_hw_ip_info
 amdgpu_query_info
+amdgpu_query_sensor_info
 amdgpu_read_mm_registers
 amdgpu_va_range_alloc
 amdgpu_va_range_free
 amdgpu_va_range_query
+amdgpu_vm_reserve_vmid
+amdgpu_vm_unreserve_vmid
 EOF
 done)
 
diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h
index 7b26a04..36f9105 100644
--- a/amdgpu/amdgpu.h
+++ b/amdgpu/amdgpu.h
@@ -37,6 +37,10 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct drm_amdgpu_info_hw_ip;
 
 /*--------------------------------------------------------------------------*/
@@ -90,6 +94,10 @@
 	amdgpu_gpu_va_range_general = 0
 };
 
+enum amdgpu_sw_info {
+	amdgpu_sw_info_address32_hi = 0,
+};
+
 /*--------------------------------------------------------------------------*/
 /* -------------------------- Datatypes ----------------------------------- */
 /*--------------------------------------------------------------------------*/
@@ -794,8 +802,9 @@
  * context will always be executed in order (first come, first serve).
  *
  *
- * \param   dev	    - \c [in] Device handle. See #amdgpu_device_initialize()
- * \param   context - \c [out] GPU Context handle
+ * \param   dev      - \c [in] Device handle. See #amdgpu_device_initialize()
+ * \param   priority - \c [in] Context creation flags. See AMDGPU_CTX_PRIORITY_*
+ * \param   context  - \c [out] GPU Context handle
  *
  * \return   0 on success\n
  *          <0 - Negative POSIX Error code
@@ -803,6 +812,18 @@
  * \sa amdgpu_cs_ctx_free()
  *
 */
+int amdgpu_cs_ctx_create2(amdgpu_device_handle dev,
+			 uint32_t priority,
+			 amdgpu_context_handle *context);
+/**
+ * Create GPU execution Context
+ *
+ * Refer to amdgpu_cs_ctx_create2 for full documentation. This call
+ * is missing the priority parameter.
+ *
+ * \sa amdgpu_cs_ctx_create2()
+ *
+*/
 int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
 			 amdgpu_context_handle *context);
 
@@ -907,6 +928,29 @@
 				 uint64_t flags,
 				 uint32_t *expired);
 
+/**
+ *  Wait for multiple fences
+ *
+ * \param   fences      - \c [in] The fence array to wait
+ * \param   fence_count - \c [in] The fence count
+ * \param   wait_all    - \c [in] If true, wait all fences to be signaled,
+ *                                otherwise, wait at least one fence
+ * \param   timeout_ns  - \c [in] The timeout to wait, in nanoseconds
+ * \param   status      - \c [out] '1' for signaled, '0' for timeout
+ * \param   first       - \c [out] the index of the first signaled fence from @fences
+ *
+ * \return  0 on success
+ *          <0 - Negative POSIX Error code
+ *
+ * \note    Currently it supports only one amdgpu_device. All fences come from
+ *          the same amdgpu_device with the same fd.
+*/
+int amdgpu_cs_wait_fences(struct amdgpu_cs_fence *fences,
+			  uint32_t fence_count,
+			  bool wait_all,
+			  uint64_t timeout_ns,
+			  uint32_t *status, uint32_t *first);
+
 /*
  * Query / Info API
  *
@@ -1046,6 +1090,23 @@
 		      unsigned size, void *value);
 
 /**
+ * Query hardware or driver information.
+ *
+ * The return size is query-specific and depends on the "info_id" parameter.
+ * No more than "size" bytes is returned.
+ *
+ * \param   dev     - \c [in] Device handle. See #amdgpu_device_initialize()
+ * \param   info    - \c [in] amdgpu_sw_info_*
+ * \param   value   - \c [out] Pointer to the return value.
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX error code
+ *
+*/
+int amdgpu_query_sw_info(amdgpu_device_handle dev, enum amdgpu_sw_info info,
+			 void *value);
+
+/**
  * Query information about GDS
  *
  * \param   dev	     - \c [in] Device handle. See #amdgpu_device_initialize()
@@ -1059,6 +1120,24 @@
 			struct amdgpu_gds_resource_info *gds_info);
 
 /**
+ * Query information about sensor.
+ *
+ * The return size is query-specific and depends on the "sensor_type"
+ * parameter. No more than "size" bytes is returned.
+ *
+ * \param   dev         - \c [in] Device handle. See #amdgpu_device_initialize()
+ * \param   sensor_type - \c [in] AMDGPU_INFO_SENSOR_*
+ * \param   size        - \c [in] Size of the returned value.
+ * \param   value       - \c [out] Pointer to the return value.
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_query_sensor_info(amdgpu_device_handle dev, unsigned sensor_type,
+			     unsigned size, void *value);
+
+/**
  * Read a set of consecutive memory-mapped registers.
  * Not all registers are allowed to be read by userspace.
  *
@@ -1083,6 +1162,7 @@
  * Flag to request VA address range in the 32bit address space
 */
 #define AMDGPU_VA_RANGE_32_BIT		0x1
+#define AMDGPU_VA_RANGE_HIGH		0x2
 
 /**
  * Allocate virtual address range
@@ -1186,6 +1266,34 @@
 		    uint32_t ops);
 
 /**
+ *  VA mapping/unmapping for a buffer object or PRT region.
+ *
+ * This is not a simple drop-in extension for amdgpu_bo_va_op; instead, all
+ * parameters are treated "raw", i.e. size is not automatically aligned, and
+ * all flags must be specified explicitly.
+ *
+ * \param  dev		- \c [in] device handle
+ * \param  bo		- \c [in] BO handle (may be NULL)
+ * \param  offset	- \c [in] Start offset to map
+ * \param  size		- \c [in] Size to map
+ * \param  addr		- \c [in] Start virtual address.
+ * \param  flags	- \c [in] Supported flags for mapping/unmapping
+ * \param  ops		- \c [in] AMDGPU_VA_OP_MAP or AMDGPU_VA_OP_UNMAP
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+
+int amdgpu_bo_va_op_raw(amdgpu_device_handle dev,
+			amdgpu_bo_handle bo,
+			uint64_t offset,
+			uint64_t size,
+			uint64_t addr,
+			uint64_t flags,
+			uint32_t ops);
+
+/**
  *  create semaphore
  *
  * \param   sem	   - \c [out] semaphore handle
@@ -1255,4 +1363,216 @@
 */
 const char *amdgpu_get_marketing_name(amdgpu_device_handle dev);
 
+/**
+ *  Create kernel sync object
+ *
+ * \param   dev         - \c [in]  device handle
+ * \param   flags       - \c [in]  flags that affect creation
+ * \param   syncobj     - \c [out] sync object handle
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_cs_create_syncobj2(amdgpu_device_handle dev,
+			      uint32_t  flags,
+			      uint32_t *syncobj);
+
+/**
+ *  Create kernel sync object
+ *
+ * \param   dev	      - \c [in]  device handle
+ * \param   syncobj   - \c [out] sync object handle
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_cs_create_syncobj(amdgpu_device_handle dev,
+			     uint32_t *syncobj);
+/**
+ *  Destroy kernel sync object
+ *
+ * \param   dev	    - \c [in] device handle
+ * \param   syncobj - \c [in] sync object handle
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+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
+ * \param   handles - \c [in] array of sync object handles
+ * \param   num_handles - \c [in] self-explanatory
+ * \param   timeout_nsec - \c [in] self-explanatory
+ * \param   flags   - \c [in] a bitmask of DRM_SYNCOBJ_WAIT_FLAGS_*
+ * \param   first_signaled - \c [in] self-explanatory
+ *
+ * \return   0 on success\n
+ *          -ETIME - Timeout
+ *          <0 - Negative POSIX Error code
+ *
+ */
+int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev,
+			   uint32_t *handles, unsigned num_handles,
+			   int64_t timeout_nsec, unsigned flags,
+			   uint32_t *first_signaled);
+
+/**
+ *  Export kernel sync object to shareable fd.
+ *
+ * \param   dev	       - \c [in] device handle
+ * \param   syncobj    - \c [in] sync object handle
+ * \param   shared_fd  - \c [out] shared file descriptor.
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_cs_export_syncobj(amdgpu_device_handle dev,
+			     uint32_t syncobj,
+			     int *shared_fd);
+/**
+ *  Import kernel sync object from shareable fd.
+ *
+ * \param   dev	       - \c [in] device handle
+ * \param   shared_fd  - \c [in] shared file descriptor.
+ * \param   syncobj    - \c [out] sync object handle
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+*/
+int amdgpu_cs_import_syncobj(amdgpu_device_handle dev,
+			     int shared_fd,
+			     uint32_t *syncobj);
+
+/**
+ *  Export kernel sync object to a sync_file.
+ *
+ * \param   dev	       - \c [in] device handle
+ * \param   syncobj    - \c [in] sync object handle
+ * \param   sync_file_fd - \c [out] sync_file file descriptor.
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+ */
+int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev,
+				       uint32_t syncobj,
+				       int *sync_file_fd);
+
+/**
+ *  Import kernel sync object from a sync_file.
+ *
+ * \param   dev	       - \c [in] device handle
+ * \param   syncobj    - \c [in] sync object handle
+ * \param   sync_file_fd - \c [in] sync_file file descriptor.
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+ */
+int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev,
+				       uint32_t syncobj,
+				       int sync_file_fd);
+
+/**
+ * Export an amdgpu fence as a handle (syncobj or fd).
+ *
+ * \param what		AMDGPU_FENCE_TO_HANDLE_GET_{SYNCOBJ, FD}
+ * \param out_handle	returned handle
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ */
+int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev,
+			      struct amdgpu_cs_fence *fence,
+			      uint32_t what,
+			      uint32_t *out_handle);
+
+/**
+ *  Submit raw command submission to kernel
+ *
+ * \param   dev	       - \c [in] device handle
+ * \param   context    - \c [in] context handle for context id
+ * \param   bo_list_handle - \c [in] request bo list handle (0 for none)
+ * \param   num_chunks - \c [in] number of CS chunks to submit
+ * \param   chunks     - \c [in] array of CS chunks
+ * \param   seq_no     - \c [out] output sequence number for submission.
+ *
+ * \return   0 on success\n
+ *          <0 - Negative POSIX Error code
+ *
+ */
+struct drm_amdgpu_cs_chunk;
+struct drm_amdgpu_cs_chunk_dep;
+struct drm_amdgpu_cs_chunk_data;
+
+int amdgpu_cs_submit_raw(amdgpu_device_handle dev,
+			 amdgpu_context_handle context,
+			 amdgpu_bo_list_handle bo_list_handle,
+			 int num_chunks,
+			 struct drm_amdgpu_cs_chunk *chunks,
+			 uint64_t *seq_no);
+
+void amdgpu_cs_chunk_fence_to_dep(struct amdgpu_cs_fence *fence,
+				  struct drm_amdgpu_cs_chunk_dep *dep);
+void amdgpu_cs_chunk_fence_info_to_data(struct amdgpu_cs_fence_info *fence_info,
+					struct drm_amdgpu_cs_chunk_data *data);
+
+/**
+ * Reserve VMID
+ * \param   context - \c [in]  GPU Context
+ * \param   flags - \c [in]  TBD
+ *
+ * \return  0 on success otherwise POSIX Error code
+*/
+int amdgpu_vm_reserve_vmid(amdgpu_device_handle dev, uint32_t flags);
+
+/**
+ * Free reserved VMID
+ * \param   context - \c [in]  GPU Context
+ * \param   flags - \c [in]  TBD
+ *
+ * \return  0 on success otherwise POSIX Error code
+*/
+int amdgpu_vm_unreserve_vmid(amdgpu_device_handle dev, uint32_t flags);
+
+#ifdef __cplusplus
+}
+#endif
 #endif /* #ifdef _AMDGPU_H_ */
diff --git a/amdgpu/amdgpu_asic_id.c b/amdgpu/amdgpu_asic_id.c
new file mode 100644
index 0000000..a5007ff
--- /dev/null
+++ b/amdgpu/amdgpu_asic_id.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2017 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "xf86drm.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+static int parse_one_line(struct amdgpu_device *dev, const char *line)
+{
+	char *buf, *saveptr;
+	char *s_did;
+	uint32_t did;
+	char *s_rid;
+	uint32_t rid;
+	char *s_name;
+	char *endptr;
+	int r = -EINVAL;
+
+	/* ignore empty line and commented line */
+	if (strlen(line) == 0 || line[0] == '#')
+		return -EAGAIN;
+
+	buf = strdup(line);
+	if (!buf)
+		return -ENOMEM;
+
+	/* device id */
+	s_did = strtok_r(buf, ",", &saveptr);
+	if (!s_did)
+		goto out;
+
+	did = strtol(s_did, &endptr, 16);
+	if (*endptr)
+		goto out;
+
+	if (did != dev->info.asic_id) {
+		r = -EAGAIN;
+		goto out;
+	}
+
+	/* revision id */
+	s_rid = strtok_r(NULL, ",", &saveptr);
+	if (!s_rid)
+		goto out;
+
+	rid = strtol(s_rid, &endptr, 16);
+	if (*endptr)
+		goto out;
+
+	if (rid != dev->info.pci_rev_id) {
+		r = -EAGAIN;
+		goto out;
+	}
+
+	/* marketing name */
+	s_name = strtok_r(NULL, ",", &saveptr);
+	if (!s_name)
+		goto out;
+
+	/* trim leading whitespaces or tabs */
+	while (isblank(*s_name))
+		s_name++;
+	if (strlen(s_name) == 0)
+		goto out;
+
+	dev->marketing_name = strdup(s_name);
+	if (dev->marketing_name)
+		r = 0;
+	else
+		r = -ENOMEM;
+
+out:
+	free(buf);
+
+	return r;
+}
+
+void amdgpu_parse_asic_ids(struct amdgpu_device *dev)
+{
+	FILE *fp;
+	char *line = NULL;
+	size_t len = 0;
+	ssize_t n;
+	int line_num = 1;
+	int r = 0;
+
+	fp = fopen(AMDGPU_ASIC_ID_TABLE, "r");
+	if (!fp) {
+		fprintf(stderr, "%s: %s\n", AMDGPU_ASIC_ID_TABLE,
+			strerror(errno));
+		return;
+	}
+
+	/* 1st valid line is file version */
+	while ((n = getline(&line, &len, fp)) != -1) {
+		/* trim trailing newline */
+		if (line[n - 1] == '\n')
+			line[n - 1] = '\0';
+
+		/* ignore empty line and commented line */
+		if (strlen(line) == 0 || line[0] == '#') {
+			line_num++;
+			continue;
+		}
+
+		drmMsg("%s version: %s\n", AMDGPU_ASIC_ID_TABLE, line);
+		break;
+	}
+
+	while ((n = getline(&line, &len, fp)) != -1) {
+		/* trim trailing newline */
+		if (line[n - 1] == '\n')
+			line[n - 1] = '\0';
+
+		r = parse_one_line(dev, line);
+		if (r != -EAGAIN)
+			break;
+
+		line_num++;
+	}
+
+	if (r == -EINVAL) {
+		fprintf(stderr, "Invalid format: %s: line %d: %s\n",
+			AMDGPU_ASIC_ID_TABLE, line_num, line);
+	} else if (r && r != -EAGAIN) {
+		fprintf(stderr, "%s: Cannot parse ASIC IDs: %s\n",
+			__func__, strerror(-r));
+	}
+
+	free(line);
+	fclose(fp);
+}
diff --git a/amdgpu/amdgpu_asic_id.h b/amdgpu/amdgpu_asic_id.h
deleted file mode 100644
index 3e7d736..0000000
--- a/amdgpu/amdgpu_asic_id.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright © 2016 Advanced Micro Devices, Inc.
- * All Rights Reserved.
- *
- * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
- *
- */
-
-#ifndef __AMDGPU_ASIC_ID_H__
-#define __AMDGPU_ASIC_ID_H__
-
-static struct amdgpu_asic_id_table_t {
-	uint32_t did;
-	uint32_t rid;
-	const char *marketing_name;
-} const amdgpu_asic_id_table [] = {
-	{0x6600,	0x0,	"AMD Radeon HD 8600/8700M"},
-	{0x6600,	0x81,	"AMD Radeon R7 M370"},
-	{0x6601,	0x0,	"AMD Radeon HD 8500M/8700M"},
-	{0x6604,	0x0,	"AMD Radeon R7 M265 Series"},
-	{0x6604,	0x81,	"AMD Radeon R7 M350"},
-	{0x6605,	0x0,	"AMD Radeon R7 M260 Series"},
-	{0x6605,	0x81,	"AMD Radeon R7 M340"},
-	{0x6606,	0x0,	"AMD Radeon HD 8790M"},
-	{0x6607,	0x0,	"AMD Radeon HD8530M"},
-	{0x6608,	0x0,	"AMD FirePro W2100"},
-	{0x6610,	0x0,	"AMD Radeon HD 8600 Series"},
-	{0x6610,	0x81,	"AMD Radeon R7 350"},
-	{0x6610,	0x83,	"AMD Radeon R5 340"},
-	{0x6611,	0x0,	"AMD Radeon HD 8500 Series"},
-	{0x6613,	0x0,	"AMD Radeon HD 8500 series"},
-	{0x6617,	0xC7,	"AMD Radeon R7 240 Series"},
-	{0x6640,	0x0,	"AMD Radeon HD 8950"},
-	{0x6640,	0x80,	"AMD Radeon R9 M380"},
-	{0x6646,	0x0,	"AMD Radeon R9 M280X"},
-	{0x6646,	0x80,	"AMD Radeon R9 M470X"},
-	{0x6647,	0x0,	"AMD Radeon R9 M270X"},
-	{0x6647,	0x80,	"AMD Radeon R9 M380"},
-	{0x6649,	0x0,	"AMD FirePro W5100"},
-	{0x6658,	0x0,	"AMD Radeon R7 200 Series"},
-	{0x665C,	0x0,	"AMD Radeon HD 7700 Series"},
-	{0x665D,	0x0,	"AMD Radeon R7 200 Series"},
-	{0x665F,	0x81,	"AMD Radeon R7 300 Series"},
-	{0x6660,	0x0,	"AMD Radeon HD 8600M Series"},
-	{0x6660,	0x81,	"AMD Radeon R5 M335"},
-	{0x6660,	0x83,	"AMD Radeon R5 M330"},
-	{0x6663,	0x0,	"AMD Radeon HD 8500M Series"},
-	{0x6663,	0x83,	"AMD Radeon R5 M320"},
-	{0x6664,	0x0,	"AMD Radeon R5 M200 Series"},
-	{0x6665,	0x0,	"AMD Radeon R5 M200 Series"},
-	{0x6665,	0x83,	"AMD Radeon R5 M320"},
-	{0x6667,	0x0,	"AMD Radeon R5 M200 Series"},
-	{0x666F,	0x0,	"AMD Radeon HD 8500M"},
-	{0x6780,	0x0,	"ATI FirePro V (FireGL V) Graphics Adapter"},
-	{0x678A,	0x0,	"ATI FirePro V (FireGL V) Graphics Adapter"},
-	{0x6798,	0x0,	"AMD Radeon HD 7900 Series"},
-	{0x679A,	0x0,	"AMD Radeon HD 7900 Series"},
-	{0x679B,	0x0,	"AMD Radeon HD 7900 Series"},
-	{0x679E,	0x0,	"AMD Radeon HD 7800 Series"},
-	{0x67A0,	0x0,	"HAWAII XTGL (67A0)"},
-	{0x67A1,	0x0,	"HAWAII GL40 (67A1)"},
-	{0x67B0,	0x0,	"AMD Radeon R9 200 Series"},
-	{0x67B0,	0x80,	"AMD Radeon R9 390 Series"},
-	{0x67B1,	0x0,	"AMD Radeon R9 200 Series"},
-	{0x67B1,	0x80,	"AMD Radeon R9 390 Series"},
-	{0x67B9,	0x0,	"AMD Radeon R9 200 Series"},
-	{0x67DF,	0xC4,	"AMD Radeon RX 480 Graphics"},
-	{0x67DF,	0xC5,	"AMD Radeon RX 470 Graphics"},
-	{0x67DF,	0xC7,	"AMD Radeon RX 480 Graphics"},
-	{0x67DF,	0xCF,	"AMD Radeon RX 470 Graphics"},
-	{0x67C4,	0x00,	"AMD Radeon Pro WX 7100 Graphics"},
-	{0x67C7,	0x00,	"AMD Radeon Pro WX 5100 Graphics"},
-	{0x67C0,	0x00,	"AMD Radeon Pro WX 7100 Graphics"},
-	{0x67E0,	0x00,	"AMD Radeon Pro WX Series Graphics"},
-	{0x67E3,	0x00,	"AMD Radeon Pro WX 4100 Graphics"},
-	{0x67E8,	0x00,	"AMD Radeon Pro WX Series Graphics"},
-	{0x67E8,	0x01,	"AMD Radeon Pro WX Series Graphics"},
-	{0x67E8,	0x80,	"AMD Radeon E9260 Graphics"},
-	{0x67EB,	0x00,	"AMD Radeon Pro WX Series Graphics"},
-	{0x67EF,	0xC0,	"AMD Radeon RX Graphics"},
-	{0x67EF,	0xC1,	"AMD Radeon RX 460 Graphics"},
-	{0x67EF,	0xC5,	"AMD Radeon RX 460 Graphics"},
-	{0x67EF,	0xC7,	"AMD Radeon RX Graphics"},
-	{0x67EF,	0xCF,	"AMD Radeon RX 460 Graphics"},
-	{0x67EF,	0xEF,	"AMD Radeon RX Graphics"},
-	{0x67FF,	0xC0,	"AMD Radeon RX Graphics"},
-	{0x67FF,	0xC1,	"AMD Radeon RX Graphics"},
-	{0x6800,	0x0,	"AMD Radeon HD 7970M"},
-	{0x6801,	0x0,	"AMD Radeon(TM) HD8970M"},
-	{0x6808,	0x0,	"ATI FirePro V(FireGL V) Graphics Adapter"},
-	{0x6809,	0x0,	"ATI FirePro V(FireGL V) Graphics Adapter"},
-	{0x6810,	0x0,	"AMD Radeon(TM) HD 8800 Series"},
-	{0x6810,	0x81,	"AMD Radeon R7 370 Series"},
-	{0x6811,	0x0,	"AMD Radeon(TM) HD8800 Series"},
-	{0x6811,	0x81,	"AMD Radeon R7 300 Series"},
-	{0x6818,	0x0,	"AMD Radeon HD 7800 Series"},
-	{0x6819,	0x0,	"AMD Radeon HD 7800 Series"},
-	{0x6820,	0x0,	"AMD Radeon HD 8800M Series"},
-	{0x6820,	0x81,	"AMD Radeon R9 M375"},
-	{0x6820,	0x83,	"AMD Radeon R9 M375X"},
-	{0x6821,	0x0,	"AMD Radeon HD 8800M Series"},
-	{0x6821,	0x87,	"AMD Radeon R7 M380"},
-	{0x6821,	0x83,	"AMD Radeon R9 M370X"},
-	{0x6822,	0x0,	"AMD Radeon E8860"},
-	{0x6823,	0x0,	"AMD Radeon HD 8800M Series"},
-	{0x6825,	0x0,	"AMD Radeon HD 7800M Series"},
-	{0x6827,	0x0,	"AMD Radeon HD 7800M Series"},
-	{0x6828,	0x0,	"ATI FirePro V(FireGL V) Graphics Adapter"},
-	{0x682B,	0x0,	"AMD Radeon HD 8800M Series"},
-	{0x682B,	0x87,	"AMD Radeon R9 M360"},
-	{0x682C,	0x0,	"AMD FirePro W4100"},
-	{0x682D,	0x0,	"AMD Radeon HD 7700M Series"},
-	{0x682F,	0x0,	"AMD Radeon HD 7700M Series"},
-	{0x6835,	0x0,	"AMD Radeon R7 Series / HD 9000 Series"},
-	{0x6837,	0x0,	"AMD Radeon HD7700 Series"},
-	{0x683D,	0x0,	"AMD Radeon HD 7700 Series"},
-	{0x683F,	0x0,	"AMD Radeon HD 7700 Series"},
-	{0x6900,	0x0,	"AMD Radeon R7 M260"},
-	{0x6900,	0x81,	"AMD Radeon R7 M360"},
-	{0x6900,	0x83,	"AMD Radeon R7 M340"},
-	{0x6901,	0x0,	"AMD Radeon R5 M255"},
-	{0x6907,	0x0,	"AMD Radeon R5 M255"},
-	{0x6907,	0x87,	"AMD Radeon R5 M315"},
-	{0x6920,	0x0,	"AMD Radeon R9 M395X"},
-	{0x6920,	0x1,	"AMD Radeon R9 M390X"},
-	{0x6921,	0x0,	"AMD Radeon R9 M295X"},
-	{0x6929,	0x0,	"AMD FirePro S7150"},
-	{0x692B,	0x0,	"AMD FirePro W7100"},
-	{0x6938,	0x0,	"AMD Radeon R9 200 Series"},
-	{0x6938,	0xF0,	"AMD Radeon R9 200 Series"},
-	{0x6938,	0xF1,	"AMD Radeon R9 380 Series"},
-	{0x6939,	0xF0,	"AMD Radeon R9 200 Series"},
-	{0x6939,	0x0,	"AMD Radeon R9 200 Series"},
-	{0x6939,	0xF1,	"AMD Radeon R9 380 Series"},
-	{0x7300,	0xC8,	"AMD Radeon R9 Fury Series"},
-	{0x7300,	0xCB,	"AMD Radeon R9 Fury Series"},
-	{0x7300,	0xCA,	"AMD Radeon R9 Fury Series"},
-	{0x9874,	0xC4,	"AMD Radeon R7 Graphics"},
-	{0x9874,	0xC5,	"AMD Radeon R6 Graphics"},
-	{0x9874,	0xC6,	"AMD Radeon R6 Graphics"},
-	{0x9874,	0xC7,	"AMD Radeon R5 Graphics"},
-	{0x9874,	0x81,	"AMD Radeon R6 Graphics"},
-	{0x9874,	0x87,	"AMD Radeon R5 Graphics"},
-	{0x9874,	0x85,	"AMD Radeon R6 Graphics"},
-	{0x9874,	0x84,	"AMD Radeon R7 Graphics"},
-
-	{0x0000,	0x0,	"\0"},
-};
-#endif
diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c
index d30fd1e..9e37b14 100644
--- a/amdgpu/amdgpu_bo.c
+++ b/amdgpu/amdgpu_bo.c
@@ -22,10 +22,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -53,29 +49,6 @@
 	drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &args);
 }
 
-drm_private void amdgpu_bo_free_internal(amdgpu_bo_handle bo)
-{
-	/* Remove the buffer from the hash tables. */
-	pthread_mutex_lock(&bo->dev->bo_table_mutex);
-	util_hash_table_remove(bo->dev->bo_handles,
-			       (void*)(uintptr_t)bo->handle);
-	if (bo->flink_name) {
-		util_hash_table_remove(bo->dev->bo_flink_names,
-				       (void*)(uintptr_t)bo->flink_name);
-	}
-	pthread_mutex_unlock(&bo->dev->bo_table_mutex);
-
-	/* Release CPU access. */
-	if (bo->cpu_map_count > 0) {
-		bo->cpu_map_count = 1;
-		amdgpu_bo_cpu_unmap(bo);
-	}
-
-	amdgpu_close_kms_handle(bo->dev, bo->handle);
-	pthread_mutex_destroy(&bo->cpu_access_mutex);
-	free(bo);
-}
-
 int amdgpu_bo_alloc(amdgpu_device_handle dev,
 		    struct amdgpu_bo_alloc_request *alloc_buffer,
 		    amdgpu_bo_handle *buf_handle)
@@ -273,8 +246,9 @@
 
 	case amdgpu_bo_handle_type_dma_buf_fd:
 		amdgpu_add_handle_to_table(bo);
-		return drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC,
-				       (int*)shared_handle);
+		return drmPrimeHandleToFD(bo->dev->fd, bo->handle,
+					  DRM_CLOEXEC | DRM_RDWR,
+					  (int*)shared_handle);
 	}
 	return -EINVAL;
 }
@@ -302,6 +276,7 @@
 		/* Get a KMS handle. */
 		r = drmPrimeFDToHandle(dev->fd, shared_handle, &handle);
 		if (r) {
+			pthread_mutex_unlock(&dev->bo_table_mutex);
 			return r;
 		}
 
@@ -341,10 +316,9 @@
 	}
 
 	if (bo) {
-		pthread_mutex_unlock(&dev->bo_table_mutex);
-
 		/* The buffer already exists, just bump the refcount. */
 		atomic_inc(&bo->refcount);
+		pthread_mutex_unlock(&dev->bo_table_mutex);
 
 		output->buf_handle = bo;
 		output->alloc_size = bo->alloc_size;
@@ -419,8 +393,35 @@
 
 int amdgpu_bo_free(amdgpu_bo_handle buf_handle)
 {
-	/* Just drop the reference. */
-	amdgpu_bo_reference(&buf_handle, NULL);
+	struct amdgpu_device *dev;
+	struct amdgpu_bo *bo = buf_handle;
+
+	assert(bo != NULL);
+	dev = bo->dev;
+	pthread_mutex_lock(&dev->bo_table_mutex);
+
+	if (update_references(&bo->refcount, NULL)) {
+		/* Remove the buffer from the hash tables. */
+		util_hash_table_remove(dev->bo_handles,
+					(void*)(uintptr_t)bo->handle);
+
+		if (bo->flink_name) {
+			util_hash_table_remove(dev->bo_flink_names,
+						(void*)(uintptr_t)bo->flink_name);
+		}
+
+		/* Release CPU access. */
+		if (bo->cpu_map_count > 0) {
+			bo->cpu_map_count = 1;
+			amdgpu_bo_cpu_unmap(bo);
+		}
+
+		amdgpu_close_kms_handle(dev, bo->handle);
+		pthread_mutex_destroy(&bo->cpu_access_mutex);
+		free(bo);
+	}
+
+	pthread_mutex_unlock(&dev->bo_table_mutex);
 	return 0;
 }
 
@@ -652,7 +653,7 @@
 		return -EINVAL;
 
 	list = malloc(number_of_resources * sizeof(struct drm_amdgpu_bo_list_entry));
-	if (list == NULL)
+	if (!list)
 		return -ENOMEM;
 
 	args.in.operation = AMDGPU_BO_LIST_OP_UPDATE;
@@ -683,21 +684,37 @@
 		     uint32_t ops)
 {
 	amdgpu_device_handle dev = bo->dev;
+
+	size = ALIGN(size, getpagesize());
+
+	return amdgpu_bo_va_op_raw(dev, bo, offset, size, addr,
+				   AMDGPU_VM_PAGE_READABLE |
+				   AMDGPU_VM_PAGE_WRITEABLE |
+				   AMDGPU_VM_PAGE_EXECUTABLE, ops);
+}
+
+int amdgpu_bo_va_op_raw(amdgpu_device_handle dev,
+			amdgpu_bo_handle bo,
+			uint64_t offset,
+			uint64_t size,
+			uint64_t addr,
+			uint64_t flags,
+			uint32_t ops)
+{
 	struct drm_amdgpu_gem_va va;
 	int r;
 
-	if (ops != AMDGPU_VA_OP_MAP && ops != AMDGPU_VA_OP_UNMAP)
+	if (ops != AMDGPU_VA_OP_MAP && ops != AMDGPU_VA_OP_UNMAP &&
+	    ops != AMDGPU_VA_OP_REPLACE && ops != AMDGPU_VA_OP_CLEAR)
 		return -EINVAL;
 
 	memset(&va, 0, sizeof(va));
-	va.handle = bo->handle;
+	va.handle = bo ? bo->handle : 0;
 	va.operation = ops;
-	va.flags = AMDGPU_VM_PAGE_READABLE |
-		   AMDGPU_VM_PAGE_WRITEABLE |
-		   AMDGPU_VM_PAGE_EXECUTABLE;
+	va.flags = flags;
 	va.va_address = addr;
 	va.offset_in_bo = offset;
-	va.map_size = ALIGN(size, getpagesize());
+	va.map_size = size;
 
 	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_VA, &va, sizeof(va));
 
diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c
index fb5b3a8..f986908 100644
--- a/amdgpu/amdgpu_cs.c
+++ b/amdgpu/amdgpu_cs.c
@@ -21,10 +21,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -46,26 +42,25 @@
 /**
  * Create command submission context
  *
- * \param   dev - \c [in] amdgpu device handle
- * \param   context - \c [out] amdgpu context handle
+ * \param   dev      - \c [in] Device handle. See #amdgpu_device_initialize()
+ * \param   priority - \c [in] Context creation flags. See AMDGPU_CTX_PRIORITY_*
+ * \param   context  - \c [out] GPU Context handle
  *
  * \return  0 on success otherwise POSIX Error code
 */
-int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
-			 amdgpu_context_handle *context)
+int amdgpu_cs_ctx_create2(amdgpu_device_handle dev, uint32_t priority,
+							amdgpu_context_handle *context)
 {
 	struct amdgpu_context *gpu_context;
 	union drm_amdgpu_ctx args;
 	int i, j, k;
 	int r;
 
-	if (NULL == dev)
-		return -EINVAL;
-	if (NULL == context)
+	if (!dev || !context)
 		return -EINVAL;
 
 	gpu_context = calloc(1, sizeof(struct amdgpu_context));
-	if (NULL == gpu_context)
+	if (!gpu_context)
 		return -ENOMEM;
 
 	gpu_context->dev = dev;
@@ -77,6 +72,8 @@
 	/* Create the context */
 	memset(&args, 0, sizeof(args));
 	args.in.op = AMDGPU_CTX_OP_ALLOC_CTX;
+	args.in.priority = priority;
+
 	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CTX, &args, sizeof(args));
 	if (r)
 		goto error;
@@ -96,6 +93,12 @@
 	return r;
 }
 
+int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
+			 amdgpu_context_handle *context)
+{
+	return amdgpu_cs_ctx_create2(dev, AMDGPU_CTX_PRIORITY_NORMAL, context);
+}
+
 /**
  * Release command submission context
  *
@@ -110,7 +113,7 @@
 	int i, j, k;
 	int r;
 
-	if (NULL == context)
+	if (!context)
 		return -EINVAL;
 
 	pthread_mutex_destroy(&context->sequence_mutex);
@@ -188,8 +191,6 @@
 		return -EINVAL;
 	if (ibs_request->ring >= AMDGPU_CS_MAX_RINGS)
 		return -EINVAL;
-	if (ibs_request->number_of_ibs > AMDGPU_CS_MAX_IBS_PER_SUBMIT)
-		return -EINVAL;
 	if (ibs_request->number_of_ibs == 0) {
 		ibs_request->seq_no = AMDGPU_NULL_SUBMIT_SEQ;
 		return 0;
@@ -330,9 +331,7 @@
 	uint32_t i;
 	int r;
 
-	if (NULL == context)
-		return -EINVAL;
-	if (NULL == ibs_request)
+	if (!context || !ibs_request)
 		return -EINVAL;
 
 	r = 0;
@@ -416,11 +415,7 @@
 	bool busy = true;
 	int r;
 
-	if (NULL == fence)
-		return -EINVAL;
-	if (NULL == expired)
-		return -EINVAL;
-	if (NULL == fence->context)
+	if (!fence || !expired || !fence->context)
 		return -EINVAL;
 	if (fence->ip_type >= AMDGPU_HW_IP_NUM)
 		return -EINVAL;
@@ -443,15 +438,83 @@
 	return r;
 }
 
+static int amdgpu_ioctl_wait_fences(struct amdgpu_cs_fence *fences,
+				    uint32_t fence_count,
+				    bool wait_all,
+				    uint64_t timeout_ns,
+				    uint32_t *status,
+				    uint32_t *first)
+{
+	struct drm_amdgpu_fence *drm_fences;
+	amdgpu_device_handle dev = fences[0].context->dev;
+	union drm_amdgpu_wait_fences args;
+	int r;
+	uint32_t i;
+
+	drm_fences = alloca(sizeof(struct drm_amdgpu_fence) * fence_count);
+	for (i = 0; i < fence_count; i++) {
+		drm_fences[i].ctx_id = fences[i].context->id;
+		drm_fences[i].ip_type = fences[i].ip_type;
+		drm_fences[i].ip_instance = fences[i].ip_instance;
+		drm_fences[i].ring = fences[i].ring;
+		drm_fences[i].seq_no = fences[i].fence;
+	}
+
+	memset(&args, 0, sizeof(args));
+	args.in.fences = (uint64_t)(uintptr_t)drm_fences;
+	args.in.fence_count = fence_count;
+	args.in.wait_all = wait_all;
+	args.in.timeout_ns = amdgpu_cs_calculate_timeout(timeout_ns);
+
+	r = drmIoctl(dev->fd, DRM_IOCTL_AMDGPU_WAIT_FENCES, &args);
+	if (r)
+		return -errno;
+
+	*status = args.out.status;
+
+	if (first)
+		*first = args.out.first_signaled;
+
+	return 0;
+}
+
+int amdgpu_cs_wait_fences(struct amdgpu_cs_fence *fences,
+			  uint32_t fence_count,
+			  bool wait_all,
+			  uint64_t timeout_ns,
+			  uint32_t *status,
+			  uint32_t *first)
+{
+	uint32_t i;
+
+	/* Sanity check */
+	if (!fences || !status || !fence_count)
+		return -EINVAL;
+
+	for (i = 0; i < fence_count; i++) {
+		if (NULL == fences[i].context)
+			return -EINVAL;
+		if (fences[i].ip_type >= AMDGPU_HW_IP_NUM)
+			return -EINVAL;
+		if (fences[i].ring >= AMDGPU_CS_MAX_RINGS)
+			return -EINVAL;
+	}
+
+	*status = 0;
+
+	return amdgpu_ioctl_wait_fences(fences, fence_count, wait_all,
+					timeout_ns, status, first);
+}
+
 int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem)
 {
 	struct amdgpu_semaphore *gpu_semaphore;
 
-	if (NULL == sem)
+	if (!sem)
 		return -EINVAL;
 
 	gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore));
-	if (NULL == gpu_semaphore)
+	if (!gpu_semaphore)
 		return -ENOMEM;
 
 	atomic_set(&gpu_semaphore->refcount, 1);
@@ -466,14 +529,12 @@
 			       uint32_t ring,
 			       amdgpu_semaphore_handle sem)
 {
-	if (NULL == ctx)
+	if (!ctx || !sem)
 		return -EINVAL;
 	if (ip_type >= AMDGPU_HW_IP_NUM)
 		return -EINVAL;
 	if (ring >= AMDGPU_CS_MAX_RINGS)
 		return -EINVAL;
-	if (NULL == sem)
-		return -EINVAL;
 	/* sem has been signaled */
 	if (sem->signal_fence.context)
 		return -EINVAL;
@@ -494,16 +555,14 @@
 			     uint32_t ring,
 			     amdgpu_semaphore_handle sem)
 {
-	if (NULL == ctx)
+	if (!ctx || !sem)
 		return -EINVAL;
 	if (ip_type >= AMDGPU_HW_IP_NUM)
 		return -EINVAL;
 	if (ring >= AMDGPU_CS_MAX_RINGS)
 		return -EINVAL;
-	if (NULL == sem)
-		return -EINVAL;
 	/* must signal first */
-	if (NULL == sem->signal_fence.context)
+	if (!sem->signal_fence.context)
 		return -EINVAL;
 
 	pthread_mutex_lock(&ctx->sequence_mutex);
@@ -514,12 +573,10 @@
 
 static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem)
 {
-	if (NULL == sem)
-		return -EINVAL;
-	if (NULL == sem->signal_fence.context)
+	if (!sem || !sem->signal_fence.context)
 		return -EINVAL;
 
-	sem->signal_fence.context = NULL;;
+	sem->signal_fence.context = NULL;
 	sem->signal_fence.ip_type = 0;
 	sem->signal_fence.ip_instance = 0;
 	sem->signal_fence.ring = 0;
@@ -530,7 +587,7 @@
 
 static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem)
 {
-	if (NULL == sem)
+	if (!sem)
 		return -EINVAL;
 
 	if (update_references(&sem->refcount, NULL))
@@ -542,3 +599,172 @@
 {
 	return amdgpu_cs_unreference_sem(sem);
 }
+
+int amdgpu_cs_create_syncobj2(amdgpu_device_handle dev,
+			      uint32_t  flags,
+			      uint32_t *handle)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjCreate(dev->fd, flags, handle);
+}
+
+int amdgpu_cs_create_syncobj(amdgpu_device_handle dev,
+			     uint32_t *handle)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjCreate(dev->fd, 0, handle);
+}
+
+int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev,
+			      uint32_t handle)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	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,
+			   uint32_t *first_signaled)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjWait(dev->fd, handles, num_handles, timeout_nsec,
+			      flags, first_signaled);
+}
+
+int amdgpu_cs_export_syncobj(amdgpu_device_handle dev,
+			     uint32_t handle,
+			     int *shared_fd)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjHandleToFD(dev->fd, handle, shared_fd);
+}
+
+int amdgpu_cs_import_syncobj(amdgpu_device_handle dev,
+			     int shared_fd,
+			     uint32_t *handle)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjFDToHandle(dev->fd, shared_fd, handle);
+}
+
+int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev,
+				       uint32_t syncobj,
+				       int *sync_file_fd)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjExportSyncFile(dev->fd, syncobj, sync_file_fd);
+}
+
+int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev,
+				       uint32_t syncobj,
+				       int sync_file_fd)
+{
+	if (NULL == dev)
+		return -EINVAL;
+
+	return drmSyncobjImportSyncFile(dev->fd, syncobj, sync_file_fd);
+}
+
+int amdgpu_cs_submit_raw(amdgpu_device_handle dev,
+			 amdgpu_context_handle context,
+			 amdgpu_bo_list_handle bo_list_handle,
+			 int num_chunks,
+			 struct drm_amdgpu_cs_chunk *chunks,
+			 uint64_t *seq_no)
+{
+	union drm_amdgpu_cs cs;
+	uint64_t *chunk_array;
+	int i, r;
+	if (num_chunks == 0)
+		return -EINVAL;
+
+	memset(&cs, 0, sizeof(cs));
+	chunk_array = alloca(sizeof(uint64_t) * num_chunks);
+	for (i = 0; i < num_chunks; i++)
+		chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i];
+	cs.in.chunks = (uint64_t)(uintptr_t)chunk_array;
+	cs.in.ctx_id = context->id;
+	cs.in.bo_list_handle = bo_list_handle ? bo_list_handle->handle : 0;
+	cs.in.num_chunks = num_chunks;
+	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CS,
+				&cs, sizeof(cs));
+	if (r)
+		return r;
+
+	if (seq_no)
+		*seq_no = cs.out.handle;
+	return 0;
+}
+
+void amdgpu_cs_chunk_fence_info_to_data(struct amdgpu_cs_fence_info *fence_info,
+					struct drm_amdgpu_cs_chunk_data *data)
+{
+	data->fence_data.handle = fence_info->handle->handle;
+	data->fence_data.offset = fence_info->offset * sizeof(uint64_t);
+}
+
+void amdgpu_cs_chunk_fence_to_dep(struct amdgpu_cs_fence *fence,
+				  struct drm_amdgpu_cs_chunk_dep *dep)
+{
+	dep->ip_type = fence->ip_type;
+	dep->ip_instance = fence->ip_instance;
+	dep->ring = fence->ring;
+	dep->ctx_id = fence->context->id;
+	dep->handle = fence->fence;
+}
+
+int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev,
+			      struct amdgpu_cs_fence *fence,
+			      uint32_t what,
+			      uint32_t *out_handle)
+{
+	union drm_amdgpu_fence_to_handle fth;
+	int r;
+
+	memset(&fth, 0, sizeof(fth));
+	fth.in.fence.ctx_id = fence->context->id;
+	fth.in.fence.ip_type = fence->ip_type;
+	fth.in.fence.ip_instance = fence->ip_instance;
+	fth.in.fence.ring = fence->ring;
+	fth.in.fence.seq_no = fence->fence;
+	fth.in.what = what;
+
+	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_FENCE_TO_HANDLE,
+				&fth, sizeof(fth));
+	if (r == 0)
+		*out_handle = fth.out.handle;
+	return r;
+}
diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c
index f4ede03..d81efcf 100644
--- a/amdgpu/amdgpu_device.c
+++ b/amdgpu/amdgpu_device.c
@@ -28,10 +28,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <sys/stat.h>
 #include <errno.h>
 #include <string.h>
@@ -44,7 +40,6 @@
 #include "amdgpu_internal.h"
 #include "util_hash_table.h"
 #include "util_math.h"
-#include "amdgpu_asic_id.h"
 
 #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
 #define UINT_TO_PTR(x) ((void *)((intptr_t)(x)))
@@ -131,10 +126,8 @@
 
 static void amdgpu_device_free_internal(amdgpu_device_handle dev)
 {
-	amdgpu_vamgr_deinit(dev->vamgr);
-	free(dev->vamgr);
-	amdgpu_vamgr_deinit(dev->vamgr_32);
-	free(dev->vamgr_32);
+	amdgpu_vamgr_deinit(&dev->vamgr_32);
+	amdgpu_vamgr_deinit(&dev->vamgr);
 	util_hash_table_destroy(dev->bo_flink_names);
 	util_hash_table_destroy(dev->bo_handles);
 	pthread_mutex_destroy(&dev->bo_table_mutex);
@@ -142,6 +135,7 @@
 	close(dev->fd);
 	if ((dev->flink_fd >= 0) && (dev->fd != dev->flink_fd))
 		close(dev->flink_fd);
+	free(dev->marketing_name);
 	free(dev);
 }
 
@@ -187,6 +181,8 @@
 		fd_tab = util_hash_table_create(fd_hash, fd_compare);
 	r = amdgpu_get_auth(fd, &flag_auth);
 	if (r) {
+		fprintf(stderr, "%s: amdgpu_get_auth (1) failed (%i)\n",
+			__func__, r);
 		pthread_mutex_unlock(&fd_mutex);
 		return r;
 	}
@@ -194,6 +190,8 @@
 	if (dev) {
 		r = amdgpu_get_auth(dev->fd, &flag_authexist);
 		if (r) {
+			fprintf(stderr, "%s: amdgpu_get_auth (2) failed (%i)\n",
+				__func__, r);
 			pthread_mutex_unlock(&fd_mutex);
 			return r;
 		}
@@ -209,6 +207,7 @@
 
 	dev = calloc(1, sizeof(struct amdgpu_device));
 	if (!dev) {
+		fprintf(stderr, "%s: calloc failed\n", __func__);
 		pthread_mutex_unlock(&fd_mutex);
 		return -ENOMEM;
 	}
@@ -244,38 +243,47 @@
 
 	/* Check if acceleration is working. */
 	r = amdgpu_query_info(dev, AMDGPU_INFO_ACCEL_WORKING, 4, &accel_working);
-	if (r)
+	if (r) {
+		fprintf(stderr, "%s: amdgpu_query_info(ACCEL_WORKING) failed (%i)\n",
+			__func__, r);
 		goto cleanup;
+	}
 	if (!accel_working) {
+		fprintf(stderr, "%s: AMDGPU_INFO_ACCEL_WORKING = 0\n", __func__);
 		r = -EBADF;
 		goto cleanup;
 	}
 
 	r = amdgpu_query_gpu_info_init(dev);
-	if (r)
+	if (r) {
+		fprintf(stderr, "%s: amdgpu_query_gpu_info_init failed\n", __func__);
 		goto cleanup;
+	}
 
-	dev->vamgr = calloc(1, sizeof(struct amdgpu_bo_va_mgr));
-	if (dev->vamgr == NULL)
-		goto cleanup;
-
-	amdgpu_vamgr_init(dev->vamgr, dev->dev_info.virtual_address_offset,
-			  dev->dev_info.virtual_address_max,
+	start = dev->dev_info.virtual_address_offset;
+	max = MIN2(dev->dev_info.virtual_address_max, 0x100000000ULL);
+	amdgpu_vamgr_init(&dev->vamgr_32, start, max,
 			  dev->dev_info.virtual_address_alignment);
 
-	max = MIN2(dev->dev_info.virtual_address_max, 0xffffffff);
-	start = amdgpu_vamgr_find_va(dev->vamgr,
-				     max - dev->dev_info.virtual_address_offset,
-				     dev->dev_info.virtual_address_alignment, 0);
-	if (start > 0xffffffff)
-		goto free_va; /* shouldn't get here */
-
-	dev->vamgr_32 =  calloc(1, sizeof(struct amdgpu_bo_va_mgr));
-	if (dev->vamgr_32 == NULL)
-		goto free_va;
-	amdgpu_vamgr_init(dev->vamgr_32, start, max,
+	start = max;
+	max = MAX2(dev->dev_info.virtual_address_max, 0x100000000ULL);
+	amdgpu_vamgr_init(&dev->vamgr, start, max,
 			  dev->dev_info.virtual_address_alignment);
 
+	start = dev->dev_info.high_va_offset;
+	max = MIN2(dev->dev_info.high_va_max, (start & ~0xffffffffULL) +
+		   0x100000000ULL);
+	amdgpu_vamgr_init(&dev->vamgr_high_32, start, max,
+			  dev->dev_info.virtual_address_alignment);
+
+	start = max;
+	max = MAX2(dev->dev_info.high_va_max, (start & ~0xffffffffULL) +
+		   0x100000000ULL);
+	amdgpu_vamgr_init(&dev->vamgr_high, start, max,
+			  dev->dev_info.virtual_address_alignment);
+
+	amdgpu_parse_asic_ids(dev);
+
 	*major_version = dev->major_version;
 	*minor_version = dev->minor_version;
 	*device_handle = dev;
@@ -284,13 +292,6 @@
 
 	return 0;
 
-free_va:
-	r = -ENOMEM;
-	amdgpu_vamgr_free_va(dev->vamgr, start,
-			     max - dev->dev_info.virtual_address_offset);
-	amdgpu_vamgr_deinit(dev->vamgr);
-	free(dev->vamgr);
-
 cleanup:
 	if (dev->fd >= 0)
 		close(dev->fd);
@@ -307,14 +308,21 @@
 
 const char *amdgpu_get_marketing_name(amdgpu_device_handle dev)
 {
-	const struct amdgpu_asic_id_table_t *t = amdgpu_asic_id_table;
+	return dev->marketing_name;
+}
 
-	while (t->did) {
-		if ((t->did == dev->info.asic_id) &&
-		    (t->rid == dev->info.pci_rev_id))
-			return t->marketing_name;
-		t++;
+int amdgpu_query_sw_info(amdgpu_device_handle dev, enum amdgpu_sw_info info,
+			 void *value)
+{
+	uint32_t *val32 = (uint32_t*)value;
+
+	switch (info) {
+	case amdgpu_sw_info_address32_hi:
+		if (dev->vamgr_high_32.va_max)
+			*val32 = (dev->vamgr_high_32.va_max - 1) >> 32;
+		else
+			*val32 = (dev->vamgr_32.va_max - 1) >> 32;
+		return 0;
 	}
-
-	return NULL;
+	return -EINVAL;
 }
diff --git a/amdgpu/amdgpu_gpu_info.c b/amdgpu/amdgpu_gpu_info.c
index 66c7e0e..b68e1c4 100644
--- a/amdgpu/amdgpu_gpu_info.c
+++ b/amdgpu/amdgpu_gpu_info.c
@@ -22,10 +22,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <string.h>
 
@@ -169,54 +165,58 @@
 	dev->info.vce_harvest_config = dev->dev_info.vce_harvest_config;
 	dev->info.pci_rev_id = dev->dev_info.pci_rev;
 
-	for (i = 0; i < (int)dev->info.num_shader_engines; i++) {
-		unsigned instance = (i << AMDGPU_INFO_MMR_SE_INDEX_SHIFT) |
-				    (AMDGPU_INFO_MMR_SH_INDEX_MASK <<
-				     AMDGPU_INFO_MMR_SH_INDEX_SHIFT);
+	if (dev->info.family_id < AMDGPU_FAMILY_AI) {
+		for (i = 0; i < (int)dev->info.num_shader_engines; i++) {
+			unsigned instance = (i << AMDGPU_INFO_MMR_SE_INDEX_SHIFT) |
+					    (AMDGPU_INFO_MMR_SH_INDEX_MASK <<
+					     AMDGPU_INFO_MMR_SH_INDEX_SHIFT);
 
-		r = amdgpu_read_mm_registers(dev, 0x263d, 1, instance, 0,
-					     &dev->info.backend_disable[i]);
-		if (r)
-			return r;
-		/* extract bitfield CC_RB_BACKEND_DISABLE.BACKEND_DISABLE */
-		dev->info.backend_disable[i] =
-			(dev->info.backend_disable[i] >> 16) & 0xff;
+			r = amdgpu_read_mm_registers(dev, 0x263d, 1, instance, 0,
+						     &dev->info.backend_disable[i]);
+			if (r)
+				return r;
+			/* extract bitfield CC_RB_BACKEND_DISABLE.BACKEND_DISABLE */
+			dev->info.backend_disable[i] =
+				(dev->info.backend_disable[i] >> 16) & 0xff;
 
-		r = amdgpu_read_mm_registers(dev, 0xa0d4, 1, instance, 0,
-					     &dev->info.pa_sc_raster_cfg[i]);
+			r = amdgpu_read_mm_registers(dev, 0xa0d4, 1, instance, 0,
+						     &dev->info.pa_sc_raster_cfg[i]);
+			if (r)
+				return r;
+
+			if (dev->info.family_id >= AMDGPU_FAMILY_CI) {
+				r = amdgpu_read_mm_registers(dev, 0xa0d5, 1, instance, 0,
+						     &dev->info.pa_sc_raster_cfg1[i]);
+				if (r)
+					return r;
+			}
+		}
+	}
+
+	r = amdgpu_read_mm_registers(dev, 0x263e, 1, 0xffffffff, 0,
+					     &dev->info.gb_addr_cfg);
+	if (r)
+		return r;
+
+	if (dev->info.family_id < AMDGPU_FAMILY_AI) {
+		r = amdgpu_read_mm_registers(dev, 0x2644, 32, 0xffffffff, 0,
+					     dev->info.gb_tile_mode);
 		if (r)
 			return r;
 
 		if (dev->info.family_id >= AMDGPU_FAMILY_CI) {
-			r = amdgpu_read_mm_registers(dev, 0xa0d5, 1, instance, 0,
-					     &dev->info.pa_sc_raster_cfg1[i]);
+			r = amdgpu_read_mm_registers(dev, 0x2664, 16, 0xffffffff, 0,
+						     dev->info.gb_macro_tile_mode);
 			if (r)
 				return r;
 		}
-	}
 
-	r = amdgpu_read_mm_registers(dev, 0x2644, 32, 0xffffffff, 0,
-				     dev->info.gb_tile_mode);
-	if (r)
-		return r;
-
-	if (dev->info.family_id >= AMDGPU_FAMILY_CI) {
-		r = amdgpu_read_mm_registers(dev, 0x2664, 16, 0xffffffff, 0,
-					     dev->info.gb_macro_tile_mode);
+		r = amdgpu_read_mm_registers(dev, 0x9d8, 1, 0xffffffff, 0,
+					     &dev->info.mc_arb_ramcfg);
 		if (r)
 			return r;
 	}
 
-	r = amdgpu_read_mm_registers(dev, 0x263e, 1, 0xffffffff, 0,
-				     &dev->info.gb_addr_cfg);
-	if (r)
-		return r;
-
-	r = amdgpu_read_mm_registers(dev, 0x9d8, 1, 0xffffffff, 0,
-				     &dev->info.mc_arb_ramcfg);
-	if (r)
-		return r;
-
 	dev->info.cu_active_number = dev->dev_info.cu_active_number;
 	dev->info.cu_ao_mask = dev->dev_info.cu_ao_mask;
 	memcpy(&dev->info.cu_bitmap[0][0], &dev->dev_info.cu_bitmap[0][0], sizeof(dev->info.cu_bitmap));
@@ -230,8 +230,9 @@
 int amdgpu_query_gpu_info(amdgpu_device_handle dev,
 			struct amdgpu_gpu_info *info)
 {
-	if ((dev == NULL) || (info == NULL))
+	if (!dev || !info)
 		return -EINVAL;
+
 	/* Get ASIC info*/
 	*info = dev->info;
 
@@ -296,7 +297,7 @@
 	struct drm_amdgpu_info_gds gds_config = {};
         int r;
 
-	if (gds_info == NULL)
+	if (!gds_info)
 		return -EINVAL;
 
         r = amdgpu_query_info(dev, AMDGPU_INFO_GDS_CONFIG,
@@ -314,3 +315,18 @@
 
 	return 0;
 }
+
+int amdgpu_query_sensor_info(amdgpu_device_handle dev, unsigned sensor_type,
+			     unsigned size, void *value)
+{
+	struct drm_amdgpu_info request;
+
+	memset(&request, 0, sizeof(request));
+	request.return_pointer = (uintptr_t)value;
+	request.return_size = size;
+	request.query = AMDGPU_INFO_SENSOR;
+	request.sensor_info.type = sensor_type;
+
+	return drmCommandWrite(dev->fd, DRM_AMDGPU_INFO, &request,
+			       sizeof(struct drm_amdgpu_info));
+}
diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h
index 4f039b6..99b8ce0 100644
--- a/amdgpu/amdgpu_internal.h
+++ b/amdgpu/amdgpu_internal.h
@@ -25,10 +25,6 @@
 #ifndef _AMDGPU_INTERNAL_H_
 #define _AMDGPU_INTERNAL_H_
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <assert.h>
 #include <pthread.h>
 
@@ -53,8 +49,6 @@
 };
 
 struct amdgpu_bo_va_mgr {
-	/* the start virtual address */
-	uint64_t va_offset;
 	uint64_t va_max;
 	struct list_head va_holes;
 	pthread_mutex_t bo_va_mutex;
@@ -76,6 +70,7 @@
 	unsigned major_version;
 	unsigned minor_version;
 
+	char *marketing_name;
 	/** List of buffer handles. Protected by bo_table_mutex. */
 	struct util_hash_table *bo_handles;
 	/** List of buffer GEM flink names. Protected by bo_table_mutex. */
@@ -84,10 +79,14 @@
 	pthread_mutex_t bo_table_mutex;
 	struct drm_amdgpu_info_device dev_info;
 	struct amdgpu_gpu_info info;
-	/** The global VA manager for the whole virtual address space */
-	struct amdgpu_bo_va_mgr *vamgr;
+	/** The VA manager for the lower virtual address space */
+	struct amdgpu_bo_va_mgr vamgr;
 	/** The VA manager for the 32bit address space */
-	struct amdgpu_bo_va_mgr *vamgr_32;
+	struct amdgpu_bo_va_mgr vamgr_32;
+	/** The VA manager for the high virtual address space */
+	struct amdgpu_bo_va_mgr vamgr_high;
+	/** The VA manager for the 32bit high address space */
+	struct amdgpu_bo_va_mgr vamgr_high_32;
 };
 
 struct amdgpu_bo {
@@ -135,19 +134,12 @@
  * Functions.
  */
 
-drm_private void amdgpu_bo_free_internal(amdgpu_bo_handle bo);
-
 drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start,
 		       uint64_t max, uint64_t alignment);
 
 drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr);
 
-drm_private uint64_t
-amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size,
-		     uint64_t alignment, uint64_t base_required);
-
-drm_private void
-amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size);
+drm_private void amdgpu_parse_asic_ids(struct amdgpu_device *dev);
 
 drm_private int amdgpu_query_gpu_info_init(amdgpu_device_handle dev);
 
@@ -179,26 +171,4 @@
 	return false;
 }
 
-/**
- * Assignment between two amdgpu_bo pointers with reference counting.
- *
- * Usage:
- *    struct amdgpu_bo *dst = ... , *src = ...;
- *
- *    dst = src;
- *    // No reference counting. Only use this when you need to move
- *    // a reference from one pointer to another.
- *
- *    amdgpu_bo_reference(&dst, src);
- *    // Reference counters are updated. dst is decremented and src is
- *    // incremented. dst is freed if its reference counter is 0.
- */
-static inline void amdgpu_bo_reference(struct amdgpu_bo **dst,
-					struct amdgpu_bo *src)
-{
-	if (update_references(&(*dst)->refcount, &src->refcount))
-		amdgpu_bo_free_internal(*dst);
-	*dst = src;
-}
-
 #endif
diff --git a/amdgpu/amdgpu_vamgr.c b/amdgpu/amdgpu_vamgr.c
index 8a707cb..1de9f95 100644
--- a/amdgpu/amdgpu_vamgr.c
+++ b/amdgpu/amdgpu_vamgr.c
@@ -21,10 +21,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -34,25 +30,33 @@
 #include "util_math.h"
 
 int amdgpu_va_range_query(amdgpu_device_handle dev,
-			  enum amdgpu_gpu_va_range type, uint64_t *start, uint64_t *end)
+			  enum amdgpu_gpu_va_range type,
+			  uint64_t *start, uint64_t *end)
 {
-	if (type == amdgpu_gpu_va_range_general) {
-		*start = dev->dev_info.virtual_address_offset;
-		*end = dev->dev_info.virtual_address_max;
-		return 0;
-	}
-	return -EINVAL;
+	if (type != amdgpu_gpu_va_range_general)
+		return -EINVAL;
+
+	*start = dev->dev_info.virtual_address_offset;
+	*end = dev->dev_info.virtual_address_max;
+	return 0;
 }
 
 drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start,
-			      uint64_t max, uint64_t alignment)
+				   uint64_t max, uint64_t alignment)
 {
-	mgr->va_offset = start;
+	struct amdgpu_bo_va_hole *n;
+
 	mgr->va_max = max;
 	mgr->va_alignment = alignment;
 
 	list_inithead(&mgr->va_holes);
 	pthread_mutex_init(&mgr->bo_va_mutex, NULL);
+	pthread_mutex_lock(&mgr->bo_va_mutex);
+	n = calloc(1, sizeof(struct amdgpu_bo_va_hole));
+	n->size = mgr->va_max - start;
+	n->offset = start;
+	list_add(&n->list, &mgr->va_holes);
+	pthread_mutex_unlock(&mgr->bo_va_mutex);
 }
 
 drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr)
@@ -65,13 +69,14 @@
 	pthread_mutex_destroy(&mgr->bo_va_mutex);
 }
 
-drm_private uint64_t
+static drm_private uint64_t
 amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size,
 		     uint64_t alignment, uint64_t base_required)
 {
 	struct amdgpu_bo_va_hole *hole, *n;
 	uint64_t offset = 0, waste = 0;
 
+
 	alignment = MAX2(alignment, mgr->va_alignment);
 	size = ALIGN(size, mgr->va_alignment);
 
@@ -79,12 +84,10 @@
 		return AMDGPU_INVALID_VA_ADDRESS;
 
 	pthread_mutex_lock(&mgr->bo_va_mutex);
-	/* TODO: using more appropriate way to track the holes */
-	/* first look for a hole */
-	LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) {
+	LIST_FOR_EACH_ENTRY_SAFE_REV(hole, n, &mgr->va_holes, list) {
 		if (base_required) {
-			if(hole->offset > base_required ||
-				(hole->offset + hole->size) < (base_required + size))
+			if (hole->offset > base_required ||
+			    (hole->offset + hole->size) < (base_required + size))
 				continue;
 			waste = base_required - hole->offset;
 			offset = base_required;
@@ -123,41 +126,14 @@
 		}
 	}
 
-	if (base_required) {
-		if (base_required < mgr->va_offset) {
-			pthread_mutex_unlock(&mgr->bo_va_mutex);
-			return AMDGPU_INVALID_VA_ADDRESS;
-		}
-		offset = mgr->va_offset;
-		waste = base_required - mgr->va_offset;
-	} else {
-		offset = mgr->va_offset;
-		waste = offset % alignment;
-		waste = waste ? alignment - waste : 0;
-	}
-
-	if (offset + waste + size > mgr->va_max) {
-		pthread_mutex_unlock(&mgr->bo_va_mutex);
-		return AMDGPU_INVALID_VA_ADDRESS;
-	}
-
-	if (waste) {
-		n = calloc(1, sizeof(struct amdgpu_bo_va_hole));
-		n->size = waste;
-		n->offset = offset;
-		list_add(&n->list, &mgr->va_holes);
-	}
-
-	offset += waste;
-	mgr->va_offset += size + waste;
 	pthread_mutex_unlock(&mgr->bo_va_mutex);
-	return offset;
+	return AMDGPU_INVALID_VA_ADDRESS;
 }
 
-drm_private void
+static drm_private void
 amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size)
 {
-	struct amdgpu_bo_va_hole *hole;
+	struct amdgpu_bo_va_hole *hole, *next;
 
 	if (va == AMDGPU_INVALID_VA_ADDRESS)
 		return;
@@ -165,61 +141,47 @@
 	size = ALIGN(size, mgr->va_alignment);
 
 	pthread_mutex_lock(&mgr->bo_va_mutex);
-	if ((va + size) == mgr->va_offset) {
-		mgr->va_offset = va;
-		/* Delete uppermost hole if it reaches the new top */
-		if (!LIST_IS_EMPTY(&mgr->va_holes)) {
-			hole = container_of(mgr->va_holes.next, hole, list);
-			if ((hole->offset + hole->size) == va) {
-				mgr->va_offset = hole->offset;
+	hole = container_of(&mgr->va_holes, hole, list);
+	LIST_FOR_EACH_ENTRY(next, &mgr->va_holes, list) {
+		if (next->offset < va)
+			break;
+		hole = next;
+	}
+
+	if (&hole->list != &mgr->va_holes) {
+		/* Grow upper hole if it's adjacent */
+		if (hole->offset == (va + size)) {
+			hole->offset = va;
+			hole->size += size;
+			/* Merge lower hole if it's adjacent */
+			if (next != hole &&
+			    &next->list != &mgr->va_holes &&
+			    (next->offset + next->size) == va) {
+				next->size += hole->size;
 				list_del(&hole->list);
 				free(hole);
 			}
-		}
-	} else {
-		struct amdgpu_bo_va_hole *next;
-
-		hole = container_of(&mgr->va_holes, hole, list);
-		LIST_FOR_EACH_ENTRY(next, &mgr->va_holes, list) {
-			if (next->offset < va)
-				break;
-			hole = next;
-		}
-
-		if (&hole->list != &mgr->va_holes) {
-			/* Grow upper hole if it's adjacent */
-			if (hole->offset == (va + size)) {
-				hole->offset = va;
-				hole->size += size;
-				/* Merge lower hole if it's adjacent */
-				if (next != hole
-						&& &next->list != &mgr->va_holes
-						&& (next->offset + next->size) == va) {
-					next->size += hole->size;
-					list_del(&hole->list);
-					free(hole);
-				}
-				goto out;
-			}
-		}
-
-		/* Grow lower hole if it's adjacent */
-		if (next != hole && &next->list != &mgr->va_holes &&
-				(next->offset + next->size) == va) {
-			next->size += size;
 			goto out;
 		}
-
-		/* FIXME on allocation failure we just lose virtual address space
-		 * maybe print a warning
-		 */
-		next = calloc(1, sizeof(struct amdgpu_bo_va_hole));
-		if (next) {
-			next->size = size;
-			next->offset = va;
-			list_add(&next->list, &hole->list);
-		}
 	}
+
+	/* Grow lower hole if it's adjacent */
+	if (next != hole && &next->list != &mgr->va_holes &&
+	    (next->offset + next->size) == va) {
+		next->size += size;
+		goto out;
+	}
+
+	/* FIXME on allocation failure we just lose virtual address space
+	 * maybe print a warning
+	 */
+	next = calloc(1, sizeof(struct amdgpu_bo_va_hole));
+	if (next) {
+		next->size = size;
+		next->offset = va;
+		list_add(&next->list, &hole->list);
+	}
+
 out:
 	pthread_mutex_unlock(&mgr->bo_va_mutex);
 }
@@ -235,10 +197,21 @@
 {
 	struct amdgpu_bo_va_mgr *vamgr;
 
-	if (flags & AMDGPU_VA_RANGE_32_BIT)
-		vamgr = dev->vamgr_32;
-	else
-		vamgr = dev->vamgr;
+	/* Clear the flag when the high VA manager is not initialized */
+	if (flags & AMDGPU_VA_RANGE_HIGH && !dev->vamgr_high_32.va_max)
+		flags &= ~AMDGPU_VA_RANGE_HIGH;
+
+	if (flags & AMDGPU_VA_RANGE_HIGH) {
+		if (flags & AMDGPU_VA_RANGE_32_BIT)
+			vamgr = &dev->vamgr_high_32;
+		else
+			vamgr = &dev->vamgr_high;
+	} else {
+		if (flags & AMDGPU_VA_RANGE_32_BIT)
+			vamgr = &dev->vamgr_32;
+		else
+			vamgr = &dev->vamgr;
+	}
 
 	va_base_alignment = MAX2(va_base_alignment, vamgr->va_alignment);
 	size = ALIGN(size, vamgr->va_alignment);
@@ -249,7 +222,10 @@
 	if (!(flags & AMDGPU_VA_RANGE_32_BIT) &&
 	    (*va_base_allocated == AMDGPU_INVALID_VA_ADDRESS)) {
 		/* fallback to 32bit address */
-		vamgr = dev->vamgr_32;
+		if (flags & AMDGPU_VA_RANGE_HIGH)
+			vamgr = &dev->vamgr_high_32;
+		else
+			vamgr = &dev->vamgr_32;
 		*va_base_allocated = amdgpu_vamgr_find_va(vamgr, size,
 					va_base_alignment, va_base_required);
 	}
diff --git a/amdgpu/amdgpu_vm.c b/amdgpu/amdgpu_vm.c
new file mode 100644
index 0000000..da9d07f
--- /dev/null
+++ b/amdgpu/amdgpu_vm.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ */
+
+#include "amdgpu.h"
+#include "amdgpu_drm.h"
+#include "xf86drm.h"
+#include "amdgpu_internal.h"
+
+int amdgpu_vm_reserve_vmid(amdgpu_device_handle dev, uint32_t flags)
+{
+	union drm_amdgpu_vm vm;
+
+	vm.in.op = AMDGPU_VM_OP_RESERVE_VMID;
+	vm.in.flags = flags;
+
+	return drmCommandWriteRead(dev->fd, DRM_AMDGPU_VM,
+				   &vm, sizeof(vm));
+}
+
+int amdgpu_vm_unreserve_vmid(amdgpu_device_handle dev, uint32_t flags)
+{
+	union drm_amdgpu_vm vm;
+
+	vm.in.op = AMDGPU_VM_OP_UNRESERVE_VMID;
+	vm.in.flags = flags;
+
+	return drmCommandWriteRead(dev->fd, DRM_AMDGPU_VM,
+				   &vm, sizeof(vm));
+}
diff --git a/amdgpu/meson.build b/amdgpu/meson.build
new file mode 100644
index 0000000..f39d7bf
--- /dev/null
+++ b/amdgpu/meson.build
@@ -0,0 +1,66 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+
+datadir_amdgpu = join_paths(get_option('prefix'), get_option('datadir'), 'libdrm')
+
+libdrm_amdgpu = shared_library(
+  'drm_amdgpu',
+  [
+    files(
+      'amdgpu_asic_id.c', 'amdgpu_bo.c', 'amdgpu_cs.c', 'amdgpu_device.c',
+      'amdgpu_gpu_info.c', 'amdgpu_vamgr.c', 'amdgpu_vm.c', 'util_hash.c',
+      'util_hash_table.c',
+    ),
+    config_file,
+  ],
+  c_args : [
+    warn_c_args,
+    '-DAMDGPU_ASIC_ID_TABLE="@0@"'.format(join_paths(datadir_amdgpu, 'amdgpu.ids')),
+  ],
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  dependencies : [dep_pthread_stubs, dep_atomic_ops],
+  version : '1.0.0',
+  install : true,
+)
+
+install_headers('amdgpu.h', subdir : 'libdrm')
+
+pkg.generate(
+  name : 'libdrm_amdgpu',
+  libraries : libdrm_amdgpu,
+  subdirs : ['.', 'libdrm'],
+  version : meson.project_version(),
+  requires_private : 'libdrm',
+  description : 'Userspace interface to kernel DRM services for amdgpu',
+)
+
+ext_libdrm_amdgpu = declare_dependency(
+  link_with : [libdrm, libdrm_amdgpu],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+test(
+  'amdgpu-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('amdgpu-symbol-check'), libdrm_amdgpu]
+)
diff --git a/amdgpu/util_hash.c b/amdgpu/util_hash.c
index 87cb671..7e59041 100644
--- a/amdgpu/util_hash.c
+++ b/amdgpu/util_hash.c
@@ -30,10 +30,6 @@
   *   Zack Rusin <zackr@vmware.com>
   */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "util_hash.h"
 
 #include <stdlib.h>
diff --git a/amdgpu/util_hash.h b/amdgpu/util_hash.h
index 01a4779..6eed156 100644
--- a/amdgpu/util_hash.h
+++ b/amdgpu/util_hash.h
@@ -44,10 +44,6 @@
 #ifndef UTIL_HASH_H
 #define UTIL_HASH_H
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdbool.h>
 
 #include "libdrm_macros.h"
diff --git a/amdgpu/util_hash_table.c b/amdgpu/util_hash_table.c
index fa7f6ea..89a8bf9 100644
--- a/amdgpu/util_hash_table.c
+++ b/amdgpu/util_hash_table.c
@@ -38,10 +38,6 @@
  */
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "util_hash_table.h"
 #include "util_hash.h"
 
diff --git a/amdgpu/util_hash_table.h b/amdgpu/util_hash_table.h
index e000128..5e295a8 100644
--- a/amdgpu/util_hash_table.h
+++ b/amdgpu/util_hash_table.h
@@ -34,10 +34,6 @@
 #ifndef U_HASH_TABLE_H_
 #define U_HASH_TABLE_H_
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "libdrm_macros.h"
 
 /**
diff --git a/android/gralloc_handle.h b/android/gralloc_handle.h
new file mode 100644
index 0000000..bcf753d
--- /dev/null
+++ b/android/gralloc_handle.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright (C) 2010-2011 LunarG Inc.
+ * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
+ * Copyright (C) 2018 Collabora, Robert Foss <robert.foss@collabora.com>
+ *
+ * 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 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.
+ */
+
+#ifndef __ANDROID_GRALLOC_HANDLE_H__
+#define __ANDROID_GRALLOC_HANDLE_H__
+
+#include <cutils/native_handle.h>
+#include <stdint.h>
+
+/* support users of drm_gralloc/gbm_gralloc */
+#define gralloc_gbm_handle_t gralloc_handle_t
+#define gralloc_drm_handle_t gralloc_handle_t
+
+struct gralloc_handle_t {
+	native_handle_t base;
+
+	/* dma-buf file descriptor
+	 * Must be located first since, native_handle_t is allocated
+	 * using native_handle_create(), which allocates space for
+	 * sizeof(native_handle_t) + sizeof(int) * (numFds + numInts)
+	 * numFds = GRALLOC_HANDLE_NUM_FDS
+	 * numInts = GRALLOC_HANDLE_NUM_INTS
+	 * Where numFds represents the number of FDs and
+	 * numInts represents the space needed for the
+	 * remainder of this struct.
+	 * And the FDs are expected to be found first following
+	 * native_handle_t.
+	 */
+	int prime_fd;
+
+	/* api variables */
+	uint32_t magic; /* differentiate between allocator impls */
+	uint32_t version; /* api version */
+
+	uint32_t width; /* width of buffer in pixels */
+	uint32_t height; /* height of buffer in pixels */
+	uint32_t format; /* pixel format (Android) */
+	uint32_t usage; /* android libhardware usage flags */
+
+	uint32_t stride; /* the stride in bytes */
+	uint64_t modifier; /* buffer modifiers */
+
+	int data_owner; /* owner of data (for validation) */
+	union {
+		void *data; /* pointer to struct gralloc_gbm_bo_t */
+		uint64_t reserved;
+	} __attribute__((aligned(8)));
+};
+
+#define GRALLOC_HANDLE_VERSION 3
+#define GRALLOC_HANDLE_MAGIC 0x60585350
+#define GRALLOC_HANDLE_NUM_FDS 1
+#define GRALLOC_HANDLE_NUM_INTS (	\
+	((sizeof(struct gralloc_handle_t) - sizeof(native_handle_t))/sizeof(int))	\
+	 - GRALLOC_HANDLE_NUM_FDS)
+
+static inline struct gralloc_handle_t *gralloc_handle(buffer_handle_t handle)
+{
+	return (struct gralloc_handle_t *)handle;
+}
+
+/**
+ * Create a buffer handle.
+ */
+static inline native_handle_t *gralloc_handle_create(int32_t width,
+                                                     int32_t height,
+                                                     int32_t hal_format,
+                                                     int32_t usage)
+{
+	struct gralloc_handle_t *handle;
+	native_handle_t *nhandle = native_handle_create(GRALLOC_HANDLE_NUM_FDS,
+							GRALLOC_HANDLE_NUM_INTS);
+
+	if (!nhandle)
+		return NULL;
+
+	handle = gralloc_handle(nhandle);
+	handle->magic = GRALLOC_HANDLE_MAGIC;
+	handle->version = GRALLOC_HANDLE_VERSION;
+	handle->width = width;
+	handle->height = height;
+	handle->format = hal_format;
+	handle->usage = usage;
+	handle->prime_fd = -1;
+
+	return nhandle;
+}
+
+#endif
diff --git a/autogen.sh b/autogen.sh
index d82ab18..13d6991 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -6,15 +6,15 @@
 ORIGDIR=`pwd`
 cd "$srcdir"
 
-autoreconf --force --verbose --install || exit 1
-cd "$ORIGDIR" || exit $?
-
-git config --local --get format.subjectPrefix ||
+git config --local --get format.subjectPrefix >/dev/null ||
     git config --local format.subjectPrefix "PATCH libdrm" 2>/dev/null
 
-git config --local --get sendemail.to ||
+git config --local --get sendemail.to >/dev/null ||
     git config --local sendemail.to "dri-devel@lists.freedesktop.org" 2>/dev/null
 
+autoreconf --force --verbose --install || exit 1
+cd "$ORIGDIR" || exit $?
+
 if test -z "$NOCONFIGURE"; then
     "$srcdir"/configure "$@"
 fi
diff --git a/configure.ac b/configure.ac
index 1da9d86..98a350c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
 
 AC_PREREQ([2.63])
 AC_INIT([libdrm],
-        [2.4.75],
+        [2.4.91],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
         [libdrm])
 
@@ -28,6 +28,7 @@
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR([build-aux])
+PKG_PROG_PKG_CONFIG
 
 # Require xorg-macros minimum of 1.12 for XORG_WITH_XSLTPROC
 m4_ifndef([XORG_MACROS_VERSION],
@@ -44,6 +45,7 @@
 # Check for programs
 AC_PROG_CC
 AC_PROG_CC_C99
+AC_PROG_NM
 
 if test "x$ac_cv_prog_cc_c99" = xno; then
 	AC_MSG_ERROR([Building libdrm requires C99 enabled compiler])
@@ -53,20 +55,39 @@
 AC_SYS_LARGEFILE
 AC_FUNC_ALLOCA
 
+save_CFLAGS="$CFLAGS"
+export CFLAGS="$CFLAGS -Werror"
 AC_HEADER_MAJOR
+CFLAGS="$save_CFLAGS"
+
 AC_CHECK_HEADERS([sys/sysctl.h sys/select.h])
 
 # Initialize libtool
 LT_PREREQ([2.2])
 LT_INIT([disable-static])
 
+dnl pthread-stubs is mandatory on some BSD platforms, due to the nature of the
+dnl project. Even then there's a notable issue as described in the project README
+case "$host_os" in
+linux* | cygwin* | darwin* | solaris* | *-gnu* | gnu* | openbsd*)
+    pthread_stubs_possible="no"
+    ;;
+* )
+    pthread_stubs_possible="yes"
+    ;;
+esac
 
-
-AC_SUBST(PTHREADSTUBS_CFLAGS)
-AC_SUBST(PTHREADSTUBS_LIBS)
+if test "x$pthread_stubs_possible" = xyes; then
+    PKG_CHECK_MODULES(PTHREADSTUBS, pthread-stubs >= 0.4)
+    AC_SUBST(PTHREADSTUBS_CFLAGS)
+    AC_SUBST(PTHREADSTUBS_LIBS)
+fi
 
 pkgconfigdir=${libdir}/pkgconfig
 AC_SUBST(pkgconfigdir)
+libdrmdatadir=${datadir}/libdrm
+AC_SUBST(libdrmdatadir)
+
 AC_ARG_ENABLE([udev],
               [AS_HELP_STRING([--enable-udev],
                               [Enable support for using udev instead of mknod (default: disabled)])],
@@ -173,7 +194,9 @@
                              [AC_MSG_ERROR([Couldn't find clock_gettime])])])
 AC_SUBST([CLOCK_LIB])
 
-AC_CHECK_FUNCS([open_memstream], [HAVE_OPEN_MEMSTREAM=yes])
+AC_CHECK_FUNCS([open_memstream],
+               [AC_DEFINE([HAVE_OPEN_MEMSTREAM], 1, [Have open_memstream()])],
+               [AC_DEFINE([HAVE_OPEN_MEMSTREAM], 0)])
 
 dnl Use lots of warning flags with with gcc and compatible compilers
 
@@ -182,7 +205,7 @@
 dnl else.  If for any reason you need to force a recheck, just change
 dnl MAYBE_WARN in an ignorable way (like adding whitespace)
 
-MAYBE_WARN="-Wall -Wextra \
+MAYBE_WARN="-Wall -Wextra -Werror=undef \
 -Wsign-compare -Werror-implicit-function-declaration \
 -Wpointer-arith -Wwrite-strings -Wstrict-prototypes \
 -Wmissing-prototypes -Wmissing-declarations -Wnested-externs \
@@ -244,9 +267,13 @@
 if test "x$drm_cv_atomic_primitives" = xIntel; then
 	AC_DEFINE(HAVE_LIBDRM_ATOMIC_PRIMITIVES, 1,
 		[Enable if your compiler supports the Intel __sync_* atomic primitives])
+else
+	AC_DEFINE(HAVE_LIBDRM_ATOMIC_PRIMITIVES, 0)
 fi
 if test "x$drm_cv_atomic_primitives" = "xlibatomic-ops"; then
 	AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1, [Enable if you have libatomic-ops-dev installed])
+else
+	AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 0)
 fi
 
 dnl Print out the approapriate message considering the value set be the
@@ -325,6 +352,8 @@
 
 if test "x$UDEV" = xyes; then
 	AC_DEFINE(UDEV, 1, [Have UDEV support])
+else
+	AC_DEFINE(UDEV, 0)
 fi
 
 AC_CANONICAL_HOST
@@ -343,32 +372,34 @@
 AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" = xyes])
 if test "x$INTEL" = xyes; then
 	AC_DEFINE(HAVE_INTEL, 1, [Have intel support])
+else
+	AC_DEFINE(HAVE_INTEL, 0)
 fi
 
 AM_CONDITIONAL(HAVE_VMWGFX, [test "x$VMWGFX" = xyes])
 if test "x$VMWGFX" = xyes; then
 	AC_DEFINE(HAVE_VMWGFX, 1, [Have vmwgfx kernel headers])
+else
+	AC_DEFINE(HAVE_VMWGFX, 0)
 fi
 
 AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" = xyes])
 if test "x$NOUVEAU" = xyes; then
 	AC_DEFINE(HAVE_NOUVEAU, 1, [Have nouveau (nvidia) support])
+else
+	AC_DEFINE(HAVE_NOUVEAU, 0)
 fi
 
 AM_CONDITIONAL(HAVE_OMAP, [test "x$OMAP" = xyes])
-if test "x$OMAP" = xyes; then
-	AC_DEFINE(HAVE_OMAP, 1, [Have OMAP support])
-fi
 
 AM_CONDITIONAL(HAVE_EXYNOS, [test "x$EXYNOS" = xyes])
 if test "x$EXYNOS" = xyes; then
 	AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support])
+else
+	AC_DEFINE(HAVE_EXYNOS, 0)
 fi
 
 AM_CONDITIONAL(HAVE_FREEDRENO, [test "x$FREEDRENO" = xyes])
-if test "x$FREEDRENO" = xyes; then
-	AC_DEFINE(HAVE_FREEDRENO, 1, [Have freedreno support])
-fi
 
 if test "x$FREEDRENO_KGSL" = xyes; then
 	if test "x$FREEDRENO" != xyes; then
@@ -378,11 +409,15 @@
 AM_CONDITIONAL(HAVE_FREEDRENO_KGSL, [test "x$FREEDRENO_KGSL" = xyes])
 if test "x$FREEDRENO_KGSL" = xyes; then
 	AC_DEFINE(HAVE_FREEDRENO_KGSL, 1, [Have freedreno support for KGSL kernel interface])
+else
+	AC_DEFINE(HAVE_FREEDRENO_KGSL, 0)
 fi
 
 AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" = xyes])
 if test "x$RADEON" = xyes; then
 	AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
+else
+	AC_DEFINE(HAVE_RADEON, 0)
 fi
 
 if test "x$AMDGPU" != xno; then
@@ -409,36 +444,30 @@
 if test "x$AMDGPU" = xyes; then
 	AC_DEFINE(HAVE_AMDGPU, 1, [Have amdgpu support])
 
-	AC_DEFINE(HAVE_CUNIT, [test "x$have_cunit" != "xno"], [Enable CUNIT Have amdgpu support])
-
 	if test "x$have_cunit" = "xno"; then
 		AC_MSG_WARN([Could not find cunit library. Disabling amdgpu tests])
 	fi
+else
+	AC_DEFINE(HAVE_AMDGPU, 0)
 fi
 
 AM_CONDITIONAL(HAVE_TEGRA, [test "x$TEGRA" = xyes])
-if test "x$TEGRA" = xyes; then
-	AC_DEFINE(HAVE_TEGRA, 1, [Have Tegra support])
-fi
 
 AM_CONDITIONAL(HAVE_ROCKCHIP, [test "x$ROCKCHIP" = xyes])
 if test "x$ROCKCHIP" = xyes; then
 	AC_DEFINE(HAVE_ROCKCHIP, 1, [Have ROCKCHIP support])
+fi
 
 AM_CONDITIONAL(HAVE_VC4, [test "x$VC4" = xyes])
 if test "x$VC4" = xyes; then
 	AC_DEFINE(HAVE_VC4, 1, [Have VC4 support])
+else
+	AC_DEFINE(HAVE_VC4, 0)
 fi
 
 AM_CONDITIONAL(HAVE_ETNAVIV, [test "x$ETNAVIV" = xyes])
-if test "x$ETNAVIV" = xyes; then
-	AC_DEFINE(HAVE_ETNAVIV, 1, [Have etnaviv support])
-fi
 
 AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes])
-if test "x$INSTALL_TESTS" = xyes; then
-	AC_DEFINE(HAVE_INSTALL_TESTS, 1, [Install test programs])
-fi
 
 AC_ARG_ENABLE([cairo-tests],
               [AS_HELP_STRING([--enable-cairo-tests],
@@ -456,6 +485,8 @@
 		AC_MSG_ERROR([Cairo support required but not present])
 	fi
 	AC_DEFINE(HAVE_CAIRO, 1, [Have Cairo support])
+else
+	AC_DEFINE(HAVE_CAIRO, 0)
 fi
 AC_MSG_RESULT([$CAIRO])
 AM_CONDITIONAL(HAVE_CAIRO, [test "x$CAIRO" = xyes])
@@ -497,6 +528,8 @@
 		AC_MSG_ERROR([Valgrind support required but not present])
 	fi
 	AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings])
+else
+	AC_DEFINE([HAVE_VALGRIND], 0)
 fi
 
 AC_MSG_RESULT([$VALGRIND])
@@ -514,11 +547,16 @@
 
 if test "x$HAVE_ATTRIBUTE_VISIBILITY" = xyes; then
     AC_DEFINE(HAVE_VISIBILITY, 1, [Compiler supports __attribute__(("hidden"))])
+else
+    AC_DEFINE(HAVE_VISIBILITY, 0)
 fi
 
+CFLAGS="$CFLAGS -include config.h"
+
 AC_SUBST(WARN_CFLAGS)
 AC_CONFIG_FILES([
 	Makefile
+	data/Makefile
 	libkms/Makefile
 	libkms/libkms.pc
 	intel/Makefile
diff --git a/data/Android.mk b/data/Android.mk
new file mode 100644
index 0000000..62013f0
--- /dev/null
+++ b/data/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := amdgpu.ids
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hwdata
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..897a7f3
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,25 @@
+#  Copyright © 2017 Advanced Micro Devices, Inc.
+#  All Rights Reserved.
+#
+#  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
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  ADAM JACKSON 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.
+
+libdrmdatadir = @libdrmdatadir@
+if HAVE_AMDGPU
+dist_libdrmdata_DATA = amdgpu.ids
+endif
diff --git a/data/amdgpu.ids b/data/amdgpu.ids
new file mode 100644
index 0000000..1828e41
--- /dev/null
+++ b/data/amdgpu.ids
@@ -0,0 +1,187 @@
+# List of AMDGPU IDs
+#
+# Syntax:
+# device_id,	revision_id,	product_name        <-- single tab after comma
+
+1.0.0
+6600,	0,	AMD Radeon HD 8600/8700M
+6600,	81,	AMD Radeon (TM) R7 M370
+6601,	0,	AMD Radeon (TM) HD 8500M/8700M
+6604,	0,	AMD Radeon R7 M265 Series
+6604,	81,	AMD Radeon (TM) R7 M350
+6605,	0,	AMD Radeon R7 M260 Series
+6605,	81,	AMD Radeon (TM) R7 M340
+6606,	0,	AMD Radeon HD 8790M
+6607,	0,	AMD Radeon (TM) HD8530M
+6608,	0,	AMD FirePro W2100
+6610,	0,	AMD Radeon HD 8600 Series
+6610,	81,	AMD Radeon (TM) R7 350
+6610,	83,	AMD Radeon (TM) R5 340
+6611,	0,	AMD Radeon HD 8500 Series
+6613,	0,	AMD Radeon HD 8500 series
+6617,	C7,	AMD Radeon R7 240 Series
+6640,	0,	AMD Radeon HD 8950
+6640,	80,	AMD Radeon (TM) R9 M380
+6646,	0,	AMD Radeon R9 M280X
+6646,	80,	AMD Radeon (TM) R9 M470X
+6647,	0,	AMD Radeon R9 M270X
+6647,	80,	AMD Radeon (TM) R9 M380
+6649,	0,	AMD FirePro W5100
+6658,	0,	AMD Radeon R7 200 Series
+665C,	0,	AMD Radeon HD 7700 Series
+665D,	0,	AMD Radeon R7 200 Series
+665F,	81,	AMD Radeon (TM) R7 300 Series
+6660,	0,	AMD Radeon HD 8600M Series
+6660,	81,	AMD Radeon (TM) R5 M335
+6660,	83,	AMD Radeon (TM) R5 M330
+6663,	0,	AMD Radeon HD 8500M Series
+6663,	83,	AMD Radeon (TM) R5 M320
+6664,	0,	AMD Radeon R5 M200 Series
+6665,	0,	AMD Radeon R5 M200 Series
+6665,	83,	AMD Radeon (TM) R5 M320
+6667,	0,	AMD Radeon R5 M200 Series
+666F,	0,	AMD Radeon HD 8500M
+6780,	0,	ATI FirePro V (FireGL V) Graphics Adapter
+678A,	0,	ATI FirePro V (FireGL V) Graphics Adapter
+6798,	0,	AMD Radeon HD 7900 Series
+679A,	0,	AMD Radeon HD 7900 Series
+679B,	0,	AMD Radeon HD 7900 Series
+679E,	0,	AMD Radeon HD 7800 Series
+67A0,	0,	AMD Radeon FirePro W9100
+67A1,	0,	AMD Radeon FirePro W8100
+67B0,	0,	AMD Radeon R9 200 Series
+67B0,	80,	AMD Radeon (TM) R9 390 Series
+67B1,	0,	AMD Radeon R9 200 Series
+67B1,	80,	AMD Radeon (TM) R9 390 Series
+67B9,	0,	AMD Radeon R9 200 Series
+67DF,	C1,	Radeon RX 580 Series
+67DF,	C2,	Radeon RX 570 Series
+67DF,	C3,	Radeon RX 580 Series
+67DF,	C4,	AMD Radeon (TM) RX 480 Graphics
+67DF,	C5,	AMD Radeon (TM) RX 470 Graphics
+67DF,	C6,	Radeon RX 570 Series
+67DF,	C7,	AMD Radeon (TM) RX 480 Graphics
+67DF,	CF,	AMD Radeon (TM) RX 470 Graphics
+67DF,	D7,	Radeon(TM) RX 470 Graphics
+67DF,	E3,	Radeon RX Series
+67DF,	E7,	Radeon RX 580 Series
+67DF,	EF,	Radeon RX 570 Series
+67C2,	01,	AMD Radeon (TM) Pro V7350x2
+67C2,	02,	AMD Radeon (TM) Pro V7300X
+67C4,	00,	AMD Radeon (TM) Pro WX 7100 Graphics
+67C7,	00,	AMD Radeon (TM) Pro WX 5100 Graphics
+67C0,	00,	AMD Radeon (TM) Pro WX 7100 Graphics
+67D0,	01,	AMD Radeon (TM) Pro V7350x2
+67D0,	02,	AMD Radeon (TM) Pro V7300X
+67E0,	00,	AMD Radeon (TM) Pro WX Series
+67E3,	00,	AMD Radeon (TM) Pro WX 4100
+67E8,	00,	AMD Radeon (TM) Pro WX Series
+67E8,	01,	AMD Radeon (TM) Pro WX Series
+67E8,	80,	AMD Radeon (TM) E9260 Graphics
+67EB,	00,	AMD Radeon (TM) Pro V5300X
+67EF,	C0,	AMD Radeon (TM) RX Graphics
+67EF,	C1,	AMD Radeon (TM) RX 460 Graphics
+67EF,	C3,	Radeon RX Series
+67EF,	C5,	AMD Radeon (TM) RX 460 Graphics
+67EF,	C7,	AMD Radeon (TM) RX Graphics
+67EF,	CF,	AMD Radeon (TM) RX 460 Graphics
+67EF,	E0,	Radeon RX 560 Series
+67EF,	E1,	Radeon RX Series
+67EF,	E3,	Radeon RX Series
+67EF,	E5,	Radeon RX 560 Series
+67EF,	EF,	AMD Radeon (TM) RX Graphics
+67EF,	FF,	Radeon(TM) RX 460 Graphics
+67FF,	C0,	AMD Radeon (TM) RX Graphics
+67FF,	C1,	AMD Radeon (TM) RX Graphics
+67FF,	CF,	Radeon RX 560 Series
+67FF,	EF,	Radeon RX 560 Series
+67FF,	FF,	Radeon RX 550 Series
+6800,	0,	AMD Radeon HD 7970M
+6801,	0,	AMD Radeon(TM) HD8970M
+6808,	0,	ATI FirePro V(FireGL V) Graphics Adapter
+6809,	0,	ATI FirePro V(FireGL V) Graphics Adapter
+6810,	0,	AMD Radeon(TM) HD 8800 Series
+6810,	81,	AMD Radeon (TM) R7 370 Series
+6811,	0,	AMD Radeon(TM) HD8800 Series
+6811,	81,	AMD Radeon (TM) R7 300 Series
+6818,	0,	AMD Radeon HD 7800 Series
+6819,	0,	AMD Radeon HD 7800 Series
+6820,	0,	AMD Radeon HD 8800M Series
+6820,	81,	AMD Radeon (TM) R9 M375
+6820,	83,	AMD Radeon (TM) R9 M375X
+6821,	0,	AMD Radeon HD 8800M Series
+6821,	87,	AMD Radeon (TM) R7 M380
+6821,	83,	AMD Radeon R9 (TM) M370X
+6822,	0,	AMD Radeon E8860
+6823,	0,	AMD Radeon HD 8800M Series
+6825,	0,	AMD Radeon HD 7800M Series
+6827,	0,	AMD Radeon HD 7800M Series
+6828,	0,	ATI FirePro V(FireGL V) Graphics Adapter
+682B,	0,	AMD Radeon HD 8800M Series
+682B,	87,	AMD Radeon (TM) R9 M360
+682C,	0,	AMD FirePro W4100
+682D,	0,	AMD Radeon HD 7700M Series
+682F,	0,	AMD Radeon HD 7700M Series
+6835,	0,	AMD Radeon R7 Series / HD 9000 Series
+6837,	0,	AMD Radeon HD7700 Series
+683D,	0,	AMD Radeon HD 7700 Series
+683F,	0,	AMD Radeon HD 7700 Series
+6860,	00,	Radeon Instinct MI25
+6860,	01,	Radeon Pro V320
+6860,	02,	Radeon Instinct MI25
+6860,	03,	Radeon Pro V340
+6860,	04,	Radeon Instinct MI25x2
+6861,	00,	Radeon(TM) Pro WX9100
+6862,	00,	Radeon Pro SSG
+6863,	00,	Radeon Vega Frontier Edition
+6864,	03,	Radeon Pro V340
+6864,	04,	Instinct MI25x2
+6868,	00,	Radeon(TM) Pro WX8100
+686C,	00,	GLXT (Radeon Instinct MI25) MxGPU VFID
+686C,	01,	GLXT (Radeon Pro V320) MxGPU
+686C,	02,	GLXT (Radeon Instinct MI25) MxGPU
+686C,	03,	GLXT (Radeon Pro V340) MxGPU
+686C,	04,	GLXT (Radeon Instinct MI25x2) MxGPU
+687F,	C0,	Radeon RX Vega
+687F,	C1,	Radeon RX Vega
+687F,	C3,	Radeon RX Vega
+6900,	0,	AMD Radeon R7 M260
+6900,	81,	AMD Radeon (TM) R7 M360
+6900,	83,	AMD Radeon (TM) R7 M340
+6901,	0,	AMD Radeon R5 M255
+6907,	0,	AMD Radeon R5 M255
+6907,	87,	AMD Radeon (TM) R5 M315
+6920,	0,	AMD RADEON R9 M395X
+6920,	1,	AMD RADEON R9 M390X
+6921,	0,	AMD Radeon R9 M295X
+6929,	0,	AMD FirePro S7150
+692B,	0,	AMD FirePro W7100
+6938,	0,	AMD Radeon R9 200 Series
+6938,	F0,	AMD Radeon R9 200 Series
+6938,	F1,	AMD Radeon (TM) R9 380 Series
+6939,	F0,	AMD Radeon R9 200 Series
+6939,	0,	AMD Radeon R9 200 Series
+6939,	F1,	AMD Radeon (TM) R9 380 Series
+6980,	00,	Radeon Pro WX3100
+6985,	00,	AMD Radeon Pro WX3100
+6987,	80,	AMD Embedded Radeon E9171
+6995,	00,	AMD Radeon Pro WX2100
+6997,	00,	Radeon Pro WX2100
+699F,	81,	AMD Embedded Radeon E9170 Series
+699F,	C0,	Radeon 500 Series
+699F,	C3,	Radeon 500 Series
+699F,	C7,	Radeon RX 550 Series
+7300,	C1,	AMD FirePro (TM) S9300 x2
+7300,	C8,	AMD Radeon (TM) R9 Fury Series
+7300,	C9,	Radeon (TM) Pro Duo
+7300,	CB,	AMD Radeon (TM) R9 Fury Series
+7300,	CA,	AMD Radeon (TM) R9 Fury Series
+9874,	C4,	AMD Radeon R7 Graphics
+9874,	C5,	AMD Radeon R6 Graphics
+9874,	C6,	AMD Radeon R6 Graphics
+9874,	C7,	AMD Radeon R5 Graphics
+9874,	C8,	AMD Radeon R7 Graphics
+9874,	81,	AMD Radeon R6 Graphics
+9874,	87,	AMD Radeon R5 Graphics
+9874,	85,	AMD Radeon R6 Graphics
+9874,	84,	AMD Radeon R7 Graphics
diff --git a/data/meson.build b/data/meson.build
new file mode 100644
index 0000000..9c26b66
--- /dev/null
+++ b/data/meson.build
@@ -0,0 +1,27 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+if with_amdgpu
+  install_data(
+    'amdgpu.ids',
+    install_mode : 'rw-r--r--',
+    install_dir : datadir_amdgpu,
+  )
+endif
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 @@
 	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 22afd16..bc50961 100755
--- a/etnaviv/etnaviv-symbol-check
+++ b/etnaviv/etnaviv-symbol-check
@@ -39,8 +39,14 @@
 etna_cmd_stream_del
 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
+etna_perfmon_get_dom_by_name
+etna_perfmon_get_sig_by_name
 EOF
 done)
 
diff --git a/etnaviv/etnaviv_bo.c b/etnaviv/etnaviv_bo.c
index 4ad0434..32f7b34 100644
--- a/etnaviv/etnaviv_bo.c
+++ b/etnaviv/etnaviv_bo.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "etnaviv_priv.h"
 #include "etnaviv_drmif.h"
 
@@ -173,7 +169,7 @@
 	pthread_mutex_lock(&table_lock);
 
 	/* check name table first, to see if bo is already open: */
-	bo = lookup_bo(dev->name_table, req.handle);
+	bo = lookup_bo(dev->name_table, name);
 	if (bo)
 		goto out_unlock;
 
@@ -206,10 +202,15 @@
 	int ret, size;
 	uint32_t handle;
 
+	/* take the lock before calling drmPrimeFDToHandle to avoid
+	 * racing against etna_bo_del, which might invalidate the
+	 * returned handle.
+	 */
 	pthread_mutex_lock(&table_lock);
 
 	ret = drmPrimeFDToHandle(dev->fd, fd, &handle);
 	if (ret) {
+		pthread_mutex_unlock(&table_lock);
 		return NULL;
 	}
 
diff --git a/etnaviv/etnaviv_bo_cache.c b/etnaviv/etnaviv_bo_cache.c
index 8924651..c81de26 100644
--- a/etnaviv/etnaviv_bo_cache.c
+++ b/etnaviv/etnaviv_bo_cache.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "etnaviv_priv.h"
 #include "etnaviv_drmif.h"
 
@@ -124,20 +120,32 @@
 
 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;
diff --git a/etnaviv/etnaviv_cmd_stream.c b/etnaviv/etnaviv_cmd_stream.c
index 9ce3f36..1373016 100644
--- a/etnaviv/etnaviv_cmd_stream.c
+++ b/etnaviv/etnaviv_cmd_stream.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <assert.h>
 
 #include "etnaviv_drmif.h"
@@ -105,6 +101,7 @@
 
 	free(stream->buffer);
 	free(priv->submit.relocs);
+	free(priv->submit.pmrs);
 	free(priv);
 }
 
@@ -115,6 +112,7 @@
 	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)
@@ -177,7 +175,8 @@
 	return idx;
 }
 
-static void flush(struct etna_cmd_stream *stream)
+static void flush(struct etna_cmd_stream *stream, int in_fence_fd,
+		  int *out_fence_fd)
 {
 	struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
 	int ret, id = priv->pipe->id;
@@ -190,10 +189,20 @@
 		.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 */
 	};
 
+	if (in_fence_fd != -1) {
+		req.flags |= ETNA_SUBMIT_FENCE_FD_IN | ETNA_SUBMIT_NO_IMPLICIT;
+		req.fence_fd = in_fence_fd;
+	}
+
+	if (out_fence_fd)
+		req.flags |= ETNA_SUBMIT_FENCE_FD_OUT;
+
 	ret = drmCommandWriteRead(gpu->dev->fd, DRM_ETNAVIV_GEM_SUBMIT,
 			&req, sizeof(req));
 
@@ -208,11 +217,21 @@
 		bo->current_stream = NULL;
 		etna_bo_del(bo);
 	}
+
+	if (out_fence_fd)
+		*out_fence_fd = req.fence_fd;
 }
 
 void etna_cmd_stream_flush(struct etna_cmd_stream *stream)
 {
-	flush(stream);
+	flush(stream, -1, NULL);
+	reset_buffer(stream);
+}
+
+void etna_cmd_stream_flush2(struct etna_cmd_stream *stream, int in_fence_fd,
+			    int *out_fence_fd)
+{
+	flush(stream, in_fence_fd, out_fence_fd);
 	reset_buffer(stream);
 }
 
@@ -220,7 +239,7 @@
 {
 	struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
 
-	flush(stream);
+	flush(stream, -1, NULL);
 	etna_pipe_wait(priv->pipe, priv->last_timestamp, 5000);
 	reset_buffer(stream);
 }
@@ -241,3 +260,19 @@
 
 	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_device.c b/etnaviv/etnaviv_device.c
index 3ce9203..d83e8d3 100644
--- a/etnaviv/etnaviv_device.c
+++ b/etnaviv/etnaviv_device.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
diff --git a/etnaviv/etnaviv_drm.h b/etnaviv/etnaviv_drm.h
index 2584c1c..0d5c49d 100644
--- a/etnaviv/etnaviv_drm.h
+++ b/etnaviv/etnaviv_drm.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
  * Copyright (C) 2015 Etnaviv Project
  *
@@ -54,6 +55,12 @@
 #define ETNAVIV_PARAM_GPU_FEATURES_4                0x07
 #define ETNAVIV_PARAM_GPU_FEATURES_5                0x08
 #define ETNAVIV_PARAM_GPU_FEATURES_6                0x09
+#define ETNAVIV_PARAM_GPU_FEATURES_7                0x0a
+#define ETNAVIV_PARAM_GPU_FEATURES_8                0x0b
+#define ETNAVIV_PARAM_GPU_FEATURES_9                0x0c
+#define ETNAVIV_PARAM_GPU_FEATURES_10               0x0d
+#define ETNAVIV_PARAM_GPU_FEATURES_11               0x0e
+#define ETNAVIV_PARAM_GPU_FEATURES_12               0x0f
 
 #define ETNAVIV_PARAM_GPU_STREAM_COUNT              0x10
 #define ETNAVIV_PARAM_GPU_REGISTER_MAX              0x11
@@ -150,10 +157,29 @@
 	__u64 presumed;       /* in/out, presumed buffer address */
 };
 
+/* performance monitor request (pmr) */
+#define ETNA_PM_PROCESS_PRE             0x0001
+#define ETNA_PM_PROCESS_POST            0x0002
+struct drm_etnaviv_gem_submit_pmr {
+	__u32 flags;          /* in, when to process request (ETNA_PM_PROCESS_x) */
+	__u8  domain;         /* in, pm domain */
+	__u8  pad;
+	__u16 signal;         /* in, pm signal */
+	__u32 sequence;       /* in, sequence number */
+	__u32 read_offset;    /* in, offset from read_bo */
+	__u32 read_idx;       /* in, index of read_bo buffer */
+};
+
 /* Each cmdstream submit consists of a table of buffers involved, and
  * one or more cmdstream buffers.  This allows for conditional execution
  * (context-restore), and IB buffers needed for per tile/bin draw cmds.
  */
+#define ETNA_SUBMIT_NO_IMPLICIT         0x0001
+#define ETNA_SUBMIT_FENCE_FD_IN         0x0002
+#define ETNA_SUBMIT_FENCE_FD_OUT        0x0004
+#define ETNA_SUBMIT_FLAGS		(ETNA_SUBMIT_NO_IMPLICIT | \
+					 ETNA_SUBMIT_FENCE_FD_IN | \
+					 ETNA_SUBMIT_FENCE_FD_OUT)
 #define ETNA_PIPE_3D      0x00
 #define ETNA_PIPE_2D      0x01
 #define ETNA_PIPE_VG      0x02
@@ -167,6 +193,11 @@
 	__u64 bos;            /* in, ptr to array of submit_bo's */
 	__u64 relocs;         /* in, ptr to array of submit_reloc's */
 	__u64 stream;         /* in, ptr to cmdstream */
+	__u32 flags;          /* in, mask of ETNA_SUBMIT_x */
+	__s32 fence_fd;       /* in/out, fence fd (see ETNA_SUBMIT_FENCE_FD_x) */
+	__u64 pmrs;           /* in, ptr to array of submit_pmr's */
+	__u32 nr_pmrs;        /* in, number of submit_pmr's */
+	__u32 pad;
 };
 
 /* The normal way to synchronize with the GPU is just to CPU_PREP on
@@ -202,6 +233,27 @@
 	struct drm_etnaviv_timespec timeout;	/* in */
 };
 
+/*
+ * Performance Monitor (PM):
+ */
+
+struct drm_etnaviv_pm_domain {
+	__u32 pipe;       /* in */
+	__u8  iter;       /* in/out, select pm domain at index iter */
+	__u8  id;         /* out, id of domain */
+	__u16 nr_signals; /* out, how many signals does this domain provide */
+	char  name[64];   /* out, name of domain */
+};
+
+struct drm_etnaviv_pm_signal {
+	__u32 pipe;       /* in */
+	__u8  domain;     /* in, pm domain index */
+	__u8  pad;
+	__u16 iter;       /* in/out, select pm source at index iter */
+	__u16 id;         /* out, id of signal */
+	char  name[64];   /* out, name of domain */
+};
+
 #define DRM_ETNAVIV_GET_PARAM          0x00
 /* placeholder:
 #define DRM_ETNAVIV_SET_PARAM          0x01
@@ -214,7 +266,9 @@
 #define DRM_ETNAVIV_WAIT_FENCE         0x07
 #define DRM_ETNAVIV_GEM_USERPTR        0x08
 #define DRM_ETNAVIV_GEM_WAIT           0x09
-#define DRM_ETNAVIV_NUM_IOCTLS         0x0a
+#define DRM_ETNAVIV_PM_QUERY_DOM       0x0a
+#define DRM_ETNAVIV_PM_QUERY_SIG       0x0b
+#define DRM_ETNAVIV_NUM_IOCTLS         0x0c
 
 #define DRM_IOCTL_ETNAVIV_GET_PARAM    DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)
 #define DRM_IOCTL_ETNAVIV_GEM_NEW      DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)
@@ -225,6 +279,8 @@
 #define DRM_IOCTL_ETNAVIV_WAIT_FENCE   DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
 #define DRM_IOCTL_ETNAVIV_GEM_USERPTR  DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr)
 #define DRM_IOCTL_ETNAVIV_GEM_WAIT     DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)
+#define DRM_IOCTL_ETNAVIV_PM_QUERY_DOM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_DOM, struct drm_etnaviv_pm_domain)
+#define DRM_IOCTL_ETNAVIV_PM_QUERY_SIG DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_SIG, struct drm_etnaviv_pm_signal)
 
 #if defined(__cplusplus)
 }
diff --git a/etnaviv/etnaviv_drmif.h b/etnaviv/etnaviv_drmif.h
index 8119baa..5a6bef8 100644
--- a/etnaviv/etnaviv_drmif.h
+++ b/etnaviv/etnaviv_drmif.h
@@ -35,6 +35,9 @@
 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,
@@ -142,6 +145,8 @@
 void etna_cmd_stream_del(struct etna_cmd_stream *stream);
 uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream);
 void etna_cmd_stream_flush(struct etna_cmd_stream *stream);
+void etna_cmd_stream_flush2(struct etna_cmd_stream *stream, int in_fence_fd,
+			    int *out_fence_fd);
 void etna_cmd_stream_finish(struct etna_cmd_stream *stream);
 
 static inline uint32_t etna_cmd_stream_avail(struct etna_cmd_stream *stream)
@@ -188,4 +193,24 @@
 
 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);
+
+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_gpu.c b/etnaviv/etnaviv_gpu.c
index 35dec6c..f7efa02 100644
--- a/etnaviv/etnaviv_gpu.c
+++ b/etnaviv/etnaviv_gpu.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "etnaviv_priv.h"
 #include "etnaviv_drmif.h"
 
@@ -61,32 +57,13 @@
 	gpu->dev = dev;
 	gpu->core = core;
 
-	/* get specs from kernel space */
-	gpu->specs.model    	= get_param(dev, core, ETNAVIV_PARAM_GPU_MODEL);
-	gpu->specs.revision 	= get_param(dev, core, ETNAVIV_PARAM_GPU_REVISION);
-	gpu->specs.features[0] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_0);
-	gpu->specs.features[1] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_1);
-	gpu->specs.features[2] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_2);
-	gpu->specs.features[3] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_3);
-	gpu->specs.features[4] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_4);
-	gpu->specs.features[5] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_5);
-	gpu->specs.features[6] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_6);
-	gpu->specs.stream_count = get_param(dev, core, ETNA_GPU_STREAM_COUNT);
-	gpu->specs.register_max = get_param(dev, core, ETNA_GPU_REGISTER_MAX);
-	gpu->specs.thread_count = get_param(dev, core, ETNA_GPU_THREAD_COUNT);
-	gpu->specs.vertex_cache_size = get_param(dev, core, ETNA_GPU_VERTEX_CACHE_SIZE);
-	gpu->specs.shader_core_count = get_param(dev, core, ETNA_GPU_SHADER_CORE_COUNT);
-	gpu->specs.pixel_pipes = get_param(dev, core, ETNA_GPU_PIXEL_PIPES);
-	gpu->specs.vertex_output_buffer_size = get_param(dev, core, ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE);
-	gpu->specs.buffer_size = get_param(dev, core, ETNA_GPU_BUFFER_SIZE);
-	gpu->specs.instruction_count = get_param(dev, core, ETNA_GPU_INSTRUCTION_COUNT);
-	gpu->specs.num_constants = get_param(dev, core, ETNA_GPU_NUM_CONSTANTS);
-	gpu->specs.num_varyings = get_param(dev, core, ETNA_GPU_NUM_VARYINGS);
+	gpu->model    	= get_param(dev, core, ETNAVIV_PARAM_GPU_MODEL);
+	gpu->revision 	= get_param(dev, core, ETNAVIV_PARAM_GPU_REVISION);
 
-	if (!gpu->specs.model)
+	if (!gpu->model)
 		goto fail;
 
-	INFO_MSG(" GPU model:          0x%x (rev %x)", gpu->specs.model, gpu->specs.revision);
+	INFO_MSG(" GPU model:          0x%x (rev %x)", gpu->model, gpu->revision);
 
 	return gpu;
 fail:
@@ -104,66 +81,69 @@
 int etna_gpu_get_param(struct etna_gpu *gpu, enum etna_param_id param,
 		uint64_t *value)
 {
+	struct etna_device *dev = gpu->dev;
+	unsigned int core = gpu->core;
+
 	switch(param) {
 	case ETNA_GPU_MODEL:
-		*value = gpu->specs.model;
+		*value = gpu->model;
 		return 0;
 	case ETNA_GPU_REVISION:
-		*value = gpu->specs.revision;
+		*value = gpu->revision;
 		return 0;
 	case ETNA_GPU_FEATURES_0:
-		*value = gpu->specs.features[0];
+		*value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_0);
 		return 0;
 	case ETNA_GPU_FEATURES_1:
-		*value = gpu->specs.features[1];
+		*value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_1);
 		return 0;
 	case ETNA_GPU_FEATURES_2:
-		*value = gpu->specs.features[2];
+		*value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_2);
 		return 0;
 	case ETNA_GPU_FEATURES_3:
-		*value = gpu->specs.features[3];
+		*value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_3);
 		return 0;
 	case ETNA_GPU_FEATURES_4:
-		*value = gpu->specs.features[4];
+		*value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_4);
 		return 0;
 	case ETNA_GPU_FEATURES_5:
-		*value = gpu->specs.features[5];
+		*value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_5);
 		return 0;
 	case ETNA_GPU_FEATURES_6:
-		*value = gpu->specs.features[6];
+		*value = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_6);
 		return 0;
 	case ETNA_GPU_STREAM_COUNT:
-		*value = gpu->specs.stream_count;
+		*value = get_param(dev, core, ETNA_GPU_STREAM_COUNT);
 		return 0;
 	case ETNA_GPU_REGISTER_MAX:
-		*value = gpu->specs.register_max;
+		*value = get_param(dev, core, ETNA_GPU_REGISTER_MAX);
 		return 0;
 	case ETNA_GPU_THREAD_COUNT:
-		*value = gpu->specs.thread_count;
+		*value = get_param(dev, core, ETNA_GPU_THREAD_COUNT);
 		return 0;
 	case ETNA_GPU_VERTEX_CACHE_SIZE:
-		*value = gpu->specs.vertex_cache_size;
+		*value = get_param(dev, core, ETNA_GPU_VERTEX_CACHE_SIZE);
 		return 0;
 	case ETNA_GPU_SHADER_CORE_COUNT:
-		*value = gpu->specs.shader_core_count;
+		*value = get_param(dev, core, ETNA_GPU_SHADER_CORE_COUNT);
 		return 0;
 	case ETNA_GPU_PIXEL_PIPES:
-		*value = gpu->specs.pixel_pipes;
+		*value = get_param(dev, core, ETNA_GPU_PIXEL_PIPES);
 		return 0;
 	case ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE:
-		*value = gpu->specs.vertex_output_buffer_size;
+		*value = get_param(dev, core, ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE);
 		return 0;
 	case ETNA_GPU_BUFFER_SIZE:
-		*value = gpu->specs.buffer_size;
+		*value = get_param(dev, core, ETNA_GPU_BUFFER_SIZE);
 		return 0;
 	case ETNA_GPU_INSTRUCTION_COUNT:
-		*value = gpu->specs.instruction_count;
+		*value = get_param(dev, core, ETNA_GPU_INSTRUCTION_COUNT);
 		return 0;
 	case ETNA_GPU_NUM_CONSTANTS:
-		*value = gpu->specs.num_constants;
+		*value = get_param(dev, core, ETNA_GPU_NUM_CONSTANTS);
 		return 0;
 	case ETNA_GPU_NUM_VARYINGS:
-		*value = gpu->specs.num_varyings;
+		*value = get_param(dev, core, ETNA_GPU_NUM_VARYINGS);
 		return 0;
 
 	default:
diff --git a/etnaviv/etnaviv_perfmon.c b/etnaviv/etnaviv_perfmon.c
new file mode 100644
index 0000000..5f408a7
--- /dev/null
+++ b/etnaviv/etnaviv_perfmon.c
@@ -0,0 +1,185 @@
+/*
+ * 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>
+ */
+
+#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_pipe.c b/etnaviv/etnaviv_pipe.c
index 94c5d37..53954aa 100644
--- a/etnaviv/etnaviv_pipe.c
+++ b/etnaviv/etnaviv_pipe.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "etnaviv_priv.h"
 
 int etna_pipe_wait(struct etna_pipe *pipe, uint32_t timestamp, uint32_t ms)
diff --git a/etnaviv/etnaviv_priv.h b/etnaviv/etnaviv_priv.h
index feaa5ad..e45d364 100644
--- a/etnaviv/etnaviv_priv.h
+++ b/etnaviv/etnaviv_priv.h
@@ -47,25 +47,6 @@
 #include "etnaviv_drmif.h"
 #include "etnaviv_drm.h"
 
-#define VIV_FEATURES_WORD_COUNT 7
-
-struct etna_specs {
-	uint32_t model;
-	uint32_t revision;
-	uint32_t features[VIV_FEATURES_WORD_COUNT];
-	uint32_t stream_count;
-	uint32_t register_max;
-	uint32_t thread_count;
-	uint32_t shader_core_count;
-	uint32_t vertex_cache_size;
-	uint32_t vertex_output_buffer_size;
-	uint32_t pixel_pipes;
-	uint32_t instruction_count;
-	uint32_t num_constants;
-	uint32_t num_varyings;
-	uint32_t buffer_size;
-};
-
 struct etna_bo_bucket {
 	uint32_t size;
 	struct list_head list;
@@ -134,8 +115,9 @@
 
 struct etna_gpu {
 	struct etna_device *dev;
-	struct etna_specs specs;
 	uint32_t core;
+	uint32_t model;
+	uint32_t revision;
 };
 
 struct etna_pipe {
@@ -158,6 +140,10 @@
 		/* 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: */
@@ -169,6 +155,27 @@
 	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];
+};
+
+struct etna_perfmon_signal
+{
+	struct list_head head;
+	struct etna_perfmon_domain *domain;
+	uint8_t signal;
+	char name[64];
+};
+
 #define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1))
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
diff --git a/etnaviv/meson.build b/etnaviv/meson.build
new file mode 100644
index 0000000..ca2aa54
--- /dev/null
+++ b/etnaviv/meson.build
@@ -0,0 +1,59 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+
+libdrm_etnaviv = shared_library(
+  'drm_etnaviv',
+  [
+    files(
+      'etnaviv_device.c', 'etnaviv_gpu.c', 'etnaviv_bo.c', 'etnaviv_bo_cache.c',
+      'etnaviv_perfmon.c', 'etnaviv_pipe.c', 'etnaviv_cmd_stream.c',
+    ),
+    config_file
+  ],
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  c_args : warn_c_args,
+  dependencies : [dep_pthread_stubs, dep_rt, dep_atomic_ops],
+  version : '1.0.0',
+  install : true,
+)
+
+install_headers('etnaviv_drmif.h', subdir : 'libdrm')
+
+pkg.generate(
+  name : 'libdrm_etnaviv',
+  libraries : libdrm_etnaviv,
+  subdirs : ['.', 'libdrm'],
+  version : meson.project_version(),
+  requires_private : 'libdrm',
+  description : 'Userspace interface to Tegra kernel DRM services',
+)
+
+ext_libdrm_etnaviv = declare_dependency(
+  link_with : [libdrm, libdrm_etnaviv],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+test(
+  'etnaviv-symbol-check',
+  prog_bash,
+  args : [files('etnaviv-symbol-check'), libdrm_etnaviv]
+)
diff --git a/exynos/exynos-symbol-check b/exynos/exynos-symbol-check
index 9692caa..e9f1b04 100755
--- a/exynos/exynos-symbol-check
+++ b/exynos/exynos-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.am/libdrm_exynos*_HEADERS
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_exynos.so} | awk '{print $3}'| while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_exynos.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
index b961e52..e1afef6 100644
--- a/exynos/exynos_drm.c
+++ b/exynos/exynos_drm.c
@@ -24,10 +24,6 @@
  *    Inki Dae <inki.dae@samsung.com>
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -417,7 +413,7 @@
 
 	i = 0;
 	while (i < len) {
-		e = (struct drm_event *) &buffer[i];
+		e = (struct drm_event *)(buffer + i);
 		switch (e->type) {
 		case DRM_EVENT_VBLANK:
 			if (evctx->version < 1 ||
diff --git a/exynos/exynos_drmif.h b/exynos/exynos_drmif.h
index 626e399..154439b 100644
--- a/exynos/exynos_drmif.h
+++ b/exynos/exynos_drmif.h
@@ -31,6 +31,10 @@
 #include <stdint.h>
 #include "exynos_drm.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 struct exynos_device {
 	int fd;
 };
@@ -109,4 +113,8 @@
 				struct exynos_event_context *ctx);
 
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif /* EXYNOS_DRMIF_H_ */
diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c
index 7f1d105..bca884b 100644
--- a/exynos/exynos_fimg2d.c
+++ b/exynos/exynos_fimg2d.c
@@ -3,17 +3,26 @@
  * Authors:
  *	Inki Dae <inki.dae@samsung.com>
  *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -293,20 +302,6 @@
 }
 
 /*
- * g2d_reset - reset fimg2d hardware.
- *
- * @ctx: a pointer to g2d_context structure.
- *
- */
-static void g2d_reset(struct g2d_context *ctx)
-{
-	ctx->cmd_nr = 0;
-	ctx->cmd_buf_nr = 0;
-
-	g2d_add_cmd(ctx, SOFT_RESET_REG, 0x01);
-}
-
-/*
  * g2d_flush - submit all commands and values in user side command buffer
  *		to command queue aware of fimg2d dma.
  *
diff --git a/exynos/exynos_fimg2d.h b/exynos/exynos_fimg2d.h
index a825c68..a4dfbe7 100644
--- a/exynos/exynos_fimg2d.h
+++ b/exynos/exynos_fimg2d.h
@@ -3,11 +3,24 @@
  * Authors:
  *	Inki Dae <inki.dae@samsung.com>
  *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
  */
 
 #ifndef _FIMG2D_H_
diff --git a/exynos/fimg2d_reg.h b/exynos/fimg2d_reg.h
index 07dd634..d42296d 100644
--- a/exynos/fimg2d_reg.h
+++ b/exynos/fimg2d_reg.h
@@ -3,11 +3,24 @@
  * Authors:
  *	Inki Dae <inki.dae@samsung.com>
  *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
  */
 
 #ifndef _FIMG2D_REG_H_
diff --git a/exynos/meson.build b/exynos/meson.build
new file mode 100644
index 0000000..30d3640
--- /dev/null
+++ b/exynos/meson.build
@@ -0,0 +1,54 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+libdrm_exynos = shared_library(
+  'drm_exynos',
+  [files('exynos_drm.c', 'exynos_fimg2d.c'), config_file],
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  dependencies : [dep_pthread_stubs],
+  version : '1.0.0',
+  install : true,
+)
+
+install_headers('exynos_drmif.h', subdir : 'libdrm')
+install_headers('exynos_drm.h', 'exynos_fimg2d.h', subdir : 'exynos')
+
+ext_libdrm_exynos = declare_dependency(
+  link_with : [libdrm, libdrm_exynos],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+pkg.generate(
+  name : 'libdrm_exynos',
+  libraries : libdrm_exynos,
+  subdirs : ['.', 'libdrm', 'exynos'],
+  version : '0.7',
+  requires_private : 'libdrm',
+  description : 'Userspace interface to exynos kernel DRM services',
+)
+
+test(
+  'exynos-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('exynos-symbol-check'), libdrm_exynos]
+)
diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am
index 0771d14..cbb0d03 100644
--- a/freedreno/Makefile.am
+++ b/freedreno/Makefile.am
@@ -5,6 +5,7 @@
 	$(WARN_CFLAGS) \
 	-I$(top_srcdir) \
 	$(PTHREADSTUBS_CFLAGS) \
+	$(VALGRIND_CFLAGS) \
 	-I$(top_srcdir)/include/drm
 
 libdrm_freedreno_la_LTLIBRARIES = libdrm_freedreno.la
diff --git a/freedreno/freedreno-symbol-check b/freedreno/freedreno-symbol-check
index 42f2c43..3b11952 100755
--- a/freedreno/freedreno-symbol-check
+++ b/freedreno/freedreno-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.sources/LIBDRM_FREEDRENO_H_FILES
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_freedreno.so} | awk '{print $3}'| while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_freedreno.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
@@ -18,10 +18,12 @@
 fd_bo_from_fbdev
 fd_bo_from_handle
 fd_bo_from_name
+fd_bo_get_iova
 fd_bo_get_name
 fd_bo_handle
 fd_bo_map
 fd_bo_new
+fd_bo_put_iova
 fd_bo_ref
 fd_bo_size
 fd_device_del
@@ -33,6 +35,7 @@
 fd_pipe_del
 fd_pipe_get_param
 fd_pipe_new
+fd_pipe_new2
 fd_pipe_wait
 fd_pipe_wait_timeout
 fd_ringbuffer_cmd_count
diff --git a/freedreno/freedreno_bo.c b/freedreno/freedreno_bo.c
index 996d6b9..34c285f 100644
--- a/freedreno/freedreno_bo.c
+++ b/freedreno/freedreno_bo.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "freedreno_drmif.h"
 #include "freedreno_priv.h"
 
@@ -102,6 +98,8 @@
 	bo->bo_reuse = TRUE;
 	pthread_mutex_unlock(&table_lock);
 
+	VG_BO_ALLOC(bo);
+
 	return bo;
 }
 
@@ -118,6 +116,8 @@
 
 	bo = bo_from_handle(dev, size, handle);
 
+	VG_BO_ALLOC(bo);
+
 out_unlock:
 	pthread_mutex_unlock(&table_lock);
 
@@ -134,6 +134,7 @@
 	pthread_mutex_lock(&table_lock);
 	ret = drmPrimeFDToHandle(dev->fd, fd, &handle);
 	if (ret) {
+		pthread_mutex_unlock(&table_lock);
 		return NULL;
 	}
 
@@ -147,6 +148,8 @@
 
 	bo = bo_from_handle(dev, size, handle);
 
+	VG_BO_ALLOC(bo);
+
 out_unlock:
 	pthread_mutex_unlock(&table_lock);
 
@@ -177,8 +180,10 @@
 		goto out_unlock;
 
 	bo = bo_from_handle(dev, req.size, req.handle);
-	if (bo)
+	if (bo) {
 		set_name(bo, name);
+		VG_BO_ALLOC(bo);
+	}
 
 out_unlock:
 	pthread_mutex_unlock(&table_lock);
@@ -186,6 +191,16 @@
 	return bo;
 }
 
+uint64_t fd_bo_get_iova(struct fd_bo *bo)
+{
+	return bo->funcs->iova(bo);
+}
+
+void fd_bo_put_iova(struct fd_bo *bo)
+{
+	/* currently a no-op */
+}
+
 struct fd_bo * fd_bo_ref(struct fd_bo *bo)
 {
 	atomic_inc(&bo->refcnt);
@@ -213,6 +228,8 @@
 /* Called under table_lock */
 drm_private void bo_del(struct fd_bo *bo)
 {
+	VG_BO_FREE(bo);
+
 	if (bo->map)
 		drm_munmap(bo->map, bo->size);
 
@@ -315,7 +332,7 @@
 	bo->funcs->cpu_fini(bo);
 }
 
-#ifndef HAVE_FREEDRENO_KGSL
+#if !HAVE_FREEDRENO_KGSL
 struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe, int fbfd, uint32_t size)
 {
     return NULL;
diff --git a/freedreno/freedreno_bo_cache.c b/freedreno/freedreno_bo_cache.c
index 7becb0d..3b73715 100644
--- a/freedreno/freedreno_bo_cache.c
+++ b/freedreno/freedreno_bo_cache.c
@@ -26,14 +26,9 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "freedreno_drmif.h"
 #include "freedreno_priv.h"
 
-
 drm_private void bo_del(struct fd_bo *bo);
 drm_private extern pthread_mutex_t table_lock;
 
@@ -102,6 +97,7 @@
 			if (time && ((time - bo->free_time) <= 1))
 				break;
 
+			VG_BO_OBTAIN(bo);
 			list_del(&bo->list);
 			bo_del(bo);
 		}
@@ -177,6 +173,7 @@
 		*size = bucket->size;
 		bo = find_in_bucket(bucket, flags);
 		if (bo) {
+			VG_BO_OBTAIN(bo);
 			if (bo->funcs->madvise(bo, TRUE) <= 0) {
 				/* we've lost the backing pages, delete and try again: */
 				pthread_mutex_lock(&table_lock);
@@ -207,6 +204,7 @@
 		clock_gettime(CLOCK_MONOTONIC, &time);
 
 		bo->free_time = time.tv_sec;
+		VG_BO_RELEASE(bo);
 		list_addtail(&bo->list, &bucket->list);
 		fd_bo_cache_cleanup(cache, time.tv_sec);
 
diff --git a/freedreno/freedreno_device.c b/freedreno/freedreno_device.c
index fcbf140..0b42561 100644
--- a/freedreno/freedreno_device.c
+++ b/freedreno/freedreno_device.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -65,7 +61,7 @@
 
 		dev = msm_device_new(fd);
 		dev->version = version->version_minor;
-#ifdef HAVE_FREEDRENO_KGSL
+#if HAVE_FREEDRENO_KGSL
 	} else if (!strcmp(version->name, "kgsl")) {
 		DEBUG_MSG("kgsl DRM device");
 		dev = kgsl_device_new(fd);
@@ -112,12 +108,13 @@
 
 static void fd_device_del_impl(struct fd_device *dev)
 {
+	int close_fd = dev->closefd ? dev->fd : -1;
 	fd_bo_cache_cleanup(&dev->bo_cache, 0);
 	drmHashDestroy(dev->handle_table);
 	drmHashDestroy(dev->name_table);
-	if (dev->closefd)
-		close(dev->fd);
 	dev->funcs->destroy(dev);
+	if (close_fd >= 0)
+		close(close_fd);
 }
 
 drm_private void fd_device_del_locked(struct fd_device *dev)
diff --git a/freedreno/freedreno_drmif.h b/freedreno/freedreno_drmif.h
index 7a8073f..2711518 100644
--- a/freedreno/freedreno_drmif.h
+++ b/freedreno/freedreno_drmif.h
@@ -61,6 +61,7 @@
 	FD_CHIP_ID,
 	FD_MAX_FREQ,
 	FD_TIMESTAMP,
+	FD_NR_RINGS,      /* # of rings == # of distinct priority levels */
 };
 
 /* bo flags: */
@@ -93,6 +94,8 @@
 	FD_VERSION_MADVISE = 1,            /* kernel supports madvise */
 	FD_VERSION_UNLIMITED_CMDS = 1,     /* submits w/ >4 cmd buffers (growable ringbuffer) */
 	FD_VERSION_FENCE_FD = 2,           /* submit command supports in/out fences */
+	FD_VERSION_SUBMIT_QUEUES = 3,      /* submit queues and multiple priority levels */
+	FD_VERSION_BO_IOVA = 3,            /* supports fd_bo_get/put_iova() */
 };
 enum fd_version fd_device_version(struct fd_device *dev);
 
@@ -100,6 +103,7 @@
  */
 
 struct fd_pipe * fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id);
+struct fd_pipe * fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio);
 void fd_pipe_del(struct fd_pipe *pipe);
 int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param,
 		uint64_t *value);
@@ -120,6 +124,8 @@
 		uint32_t handle, uint32_t size);
 struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name);
 struct fd_bo * fd_bo_from_dmabuf(struct fd_device *dev, int fd);
+uint64_t fd_bo_get_iova(struct fd_bo *bo);
+void fd_bo_put_iova(struct fd_bo *bo);
 struct fd_bo * fd_bo_ref(struct fd_bo *bo);
 void fd_bo_del(struct fd_bo *bo);
 int fd_bo_get_name(struct fd_bo *bo, uint32_t *name);
diff --git a/freedreno/freedreno_pipe.c b/freedreno/freedreno_pipe.c
index 3f8c834..77b160e 100644
--- a/freedreno/freedreno_pipe.c
+++ b/freedreno/freedreno_pipe.c
@@ -26,28 +26,33 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "freedreno_drmif.h"
 #include "freedreno_priv.h"
 
+/**
+ * priority of zero is highest priority, and higher numeric values are
+ * lower priorities
+ */
 struct fd_pipe *
-fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
+fd_pipe_new2(struct fd_device *dev, enum fd_pipe_id id, uint32_t prio)
 {
-	struct fd_pipe *pipe = NULL;
+	struct fd_pipe *pipe;
 	uint64_t val;
 
 	if (id > FD_PIPE_MAX) {
 		ERROR_MSG("invalid pipe id: %d", id);
-		goto fail;
+		return NULL;
 	}
 
-	pipe = dev->funcs->pipe_new(dev, id);
+	if ((prio != 1) && (fd_device_version(dev) < FD_VERSION_SUBMIT_QUEUES)) {
+		ERROR_MSG("invalid priority!");
+		return NULL;
+	}
+
+	pipe = dev->funcs->pipe_new(dev, id, prio);
 	if (!pipe) {
 		ERROR_MSG("allocation failed");
-		goto fail;
+		return NULL;
 	}
 
 	pipe->dev = dev;
@@ -57,10 +62,12 @@
 	pipe->gpu_id = val;
 
 	return pipe;
-fail:
-	if (pipe)
-		fd_pipe_del(pipe);
-	return NULL;
+}
+
+struct fd_pipe *
+fd_pipe_new(struct fd_device *dev, enum fd_pipe_id id)
+{
+	return fd_pipe_new2(dev, id, 1);
 }
 
 void fd_pipe_del(struct fd_pipe *pipe)
diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h
index 3217039..6c9e509 100644
--- a/freedreno/freedreno_priv.h
+++ b/freedreno/freedreno_priv.h
@@ -29,10 +29,6 @@
 #ifndef FREEDRENO_PRIV_H_
 #define FREEDRENO_PRIV_H_
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
@@ -49,6 +45,7 @@
 #include "xf86atomic.h"
 
 #include "util_double_list.h"
+#include "util_math.h"
 
 #include "freedreno_drmif.h"
 #include "freedreno_ringbuffer.h"
@@ -66,7 +63,8 @@
 			uint32_t flags, uint32_t *handle);
 	struct fd_bo * (*bo_from_handle)(struct fd_device *dev,
 			uint32_t size, uint32_t handle);
-	struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id);
+	struct fd_pipe * (*pipe_new)(struct fd_device *dev, enum fd_pipe_id id,
+			unsigned prio);
 	void (*destroy)(struct fd_device *dev);
 };
 
@@ -102,6 +100,9 @@
 	struct fd_bo_cache bo_cache;
 
 	int closefd;        /* call close(fd) upon destruction */
+
+	/* just for valgrind: */
+	int bo_size;
 };
 
 drm_private void fd_bo_cache_init(struct fd_bo_cache *cache, int coarse);
@@ -152,6 +153,7 @@
 	int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op);
 	void (*cpu_fini)(struct fd_bo *bo);
 	int (*madvise)(struct fd_bo *bo, int willneed);
+	uint64_t (*iova)(struct fd_bo *bo);
 	void (*destroy)(struct fd_bo *bo);
 };
 
@@ -169,7 +171,6 @@
 	time_t free_time;        /* time when added to bucket-list */
 };
 
-#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1))
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
 #define enable_debug 0  /* TODO make dynamic */
@@ -196,4 +197,57 @@
 	return ((char *)end) - ((char *)start);
 }
 
+#if HAVE_VALGRIND
+#  include <memcheck.h>
+
+/*
+ * For tracking the backing memory (if valgrind enabled, we force a mmap
+ * for the purposes of tracking)
+ */
+static inline void VG_BO_ALLOC(struct fd_bo *bo)
+{
+	if (bo && RUNNING_ON_VALGRIND) {
+		VALGRIND_MALLOCLIKE_BLOCK(fd_bo_map(bo), bo->size, 0, 1);
+	}
+}
+
+static inline void VG_BO_FREE(struct fd_bo *bo)
+{
+	VALGRIND_FREELIKE_BLOCK(bo->map, 0);
+}
+
+/*
+ * For tracking bo structs that are in the buffer-cache, so that valgrind
+ * doesn't attribute ownership to the first one to allocate the recycled
+ * bo.
+ *
+ * Note that the list_head in fd_bo is used to track the buffers in cache
+ * so disable error reporting on the range while they are in cache so
+ * valgrind doesn't squawk about list traversal.
+ *
+ */
+static inline void VG_BO_RELEASE(struct fd_bo *bo)
+{
+	if (RUNNING_ON_VALGRIND) {
+		VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size);
+		VALGRIND_MAKE_MEM_NOACCESS(bo, bo->dev->bo_size);
+		VALGRIND_FREELIKE_BLOCK(bo->map, 0);
+	}
+}
+static inline void VG_BO_OBTAIN(struct fd_bo *bo)
+{
+	if (RUNNING_ON_VALGRIND) {
+		VALGRIND_MAKE_MEM_DEFINED(bo, bo->dev->bo_size);
+		VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, bo->dev->bo_size);
+		VALGRIND_MALLOCLIKE_BLOCK(bo->map, bo->size, 0, 1);
+	}
+}
+#else
+static inline void VG_BO_ALLOC(struct fd_bo *bo)   {}
+static inline void VG_BO_FREE(struct fd_bo *bo)    {}
+static inline void VG_BO_RELEASE(struct fd_bo *bo) {}
+static inline void VG_BO_OBTAIN(struct fd_bo *bo)  {}
+#endif
+
+
 #endif /* FREEDRENO_PRIV_H_ */
diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c
index 7310f1f..3834b51 100644
--- a/freedreno/freedreno_ringbuffer.c
+++ b/freedreno/freedreno_ringbuffer.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <assert.h>
 
 #include "freedreno_drmif.h"
diff --git a/freedreno/kgsl/kgsl_bo.c b/freedreno/kgsl/kgsl_bo.c
index ab3485e..c6d2d49 100644
--- a/freedreno/kgsl/kgsl_bo.c
+++ b/freedreno/kgsl/kgsl_bo.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "kgsl_priv.h"
 
 #include <linux/fb.h>
diff --git a/freedreno/kgsl/kgsl_device.c b/freedreno/kgsl/kgsl_device.c
index 175e837..914f341 100644
--- a/freedreno/kgsl/kgsl_device.c
+++ b/freedreno/kgsl/kgsl_device.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -61,5 +57,7 @@
 	dev = &kgsl_dev->base;
 	dev->funcs = &funcs;
 
+	dev->bo_size = sizeof(struct kgsl_bo);
+
 	return dev;
 }
diff --git a/freedreno/kgsl/kgsl_pipe.c b/freedreno/kgsl/kgsl_pipe.c
index 8a39eb4..0a8b658 100644
--- a/freedreno/kgsl/kgsl_pipe.c
+++ b/freedreno/kgsl/kgsl_pipe.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "kgsl_priv.h"
 
 
@@ -52,6 +48,7 @@
 		return 0;
 	case FD_MAX_FREQ:
 	case FD_TIMESTAMP:
+	case FD_NR_RINGS:
 		/* unsupported on kgsl */
 		return -1;
 	default:
@@ -210,7 +207,7 @@
 
 
 drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev,
-		enum fd_pipe_id id)
+		enum fd_pipe_id id, uint32_t prio)
 {
 	static const char *paths[] = {
 			[FD_PIPE_3D] = "/dev/kgsl-3d0",
diff --git a/freedreno/kgsl/kgsl_priv.h b/freedreno/kgsl/kgsl_priv.h
index 6ab6496..41b1392 100644
--- a/freedreno/kgsl/kgsl_priv.h
+++ b/freedreno/kgsl/kgsl_priv.h
@@ -103,7 +103,7 @@
 drm_private void kgsl_pipe_process_pending(struct kgsl_pipe *pipe,
 		uint32_t timestamp);
 drm_private struct fd_pipe * kgsl_pipe_new(struct fd_device *dev,
-		enum fd_pipe_id id);
+		enum fd_pipe_id id, uint32_t prio);
 
 drm_private struct fd_ringbuffer * kgsl_ringbuffer_new(struct fd_pipe *pipe,
 		uint32_t size);
diff --git a/freedreno/kgsl/kgsl_ringbuffer.c b/freedreno/kgsl/kgsl_ringbuffer.c
index e4696b1..a756ded 100644
--- a/freedreno/kgsl/kgsl_ringbuffer.c
+++ b/freedreno/kgsl/kgsl_ringbuffer.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <assert.h>
 
 #include "freedreno_ringbuffer.h"
@@ -146,7 +142,7 @@
 		ibdesc.gpuaddr = kgsl_ring->bo->gpuaddr;
 		ibdesc.hostptr = kgsl_ring->bo->hostptr;
 		ibdesc.sizedwords = 0x145;
-		req.timestamp = (uint32_t)kgsl_ring->bo->hostptr;
+		req.timestamp = (uintptr_t)kgsl_ring->bo->hostptr;
 	}
 
 	do {
diff --git a/freedreno/meson.build b/freedreno/meson.build
new file mode 100644
index 0000000..015b7fb
--- /dev/null
+++ b/freedreno/meson.build
@@ -0,0 +1,77 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+files_freedreno = files(
+  'freedreno_device.c',
+  'freedreno_pipe.c',
+  'freedreno_ringbuffer.c',
+  'freedreno_bo.c',
+  'freedreno_bo_cache.c',
+  'msm/msm_bo.c',
+  'msm/msm_device.c',
+  'msm/msm_pipe.c',
+  'msm/msm_ringbuffer.c',
+)
+
+if with_freedreno_kgsl
+  files_freedreno += files(
+    'kgsl/kgsl_bo.c',
+    'kgsl/kgsl_device.c',
+    'kgsl/kgsl_pipe.c',
+    'kgsl/kgsl_ringbuffer.c',
+  )
+endif
+
+libdrm_freedreno = shared_library(
+  'drm_freedreno',
+  [files_freedreno, config_file],
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_drm],
+  dependencies : [dep_valgrind, dep_pthread_stubs, dep_rt, dep_atomic_ops],
+  link_with : libdrm,
+  version : '1.0.0',
+  install : true,
+)
+
+ext_libdrm_freedreno = declare_dependency(
+  link_with : [libdrm, libdrm_freedreno],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+install_headers(
+  'freedreno_drmif.h', 'freedreno_ringbuffer.h',
+  subdir : 'freedreno'
+)
+
+pkg.generate(
+  name : 'libdrm_freedreno',
+  libraries : libdrm_freedreno,
+  subdirs : ['.', 'libdrm', 'freedreno'],
+  version : meson.project_version(),
+  requires_private : 'libdrm',
+  description : 'Userspace interface to freedreno kernel DRM services',
+)
+
+test(
+  'freedreno-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('freedreno-symbol-check'), libdrm_freedreno]
+)
diff --git a/freedreno/msm/msm_bo.c b/freedreno/msm/msm_bo.c
index 72471df..8b3d0bc 100644
--- a/freedreno/msm/msm_bo.c
+++ b/freedreno/msm/msm_bo.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "msm_priv.h"
 
 static int bo_allocate(struct msm_bo *msm_bo)
@@ -108,6 +104,18 @@
 	return req.retained;
 }
 
+static uint64_t msm_bo_iova(struct fd_bo *bo)
+{
+	struct drm_msm_gem_info req = {
+			.handle = bo->handle,
+			.flags = MSM_INFO_IOVA,
+	};
+
+	drmCommandWriteRead(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
+
+	return req.offset;
+}
+
 static void msm_bo_destroy(struct fd_bo *bo)
 {
 	struct msm_bo *msm_bo = to_msm_bo(bo);
@@ -120,6 +128,7 @@
 		.cpu_prep = msm_bo_cpu_prep,
 		.cpu_fini = msm_bo_cpu_fini,
 		.madvise = msm_bo_madvise,
+		.iova = msm_bo_iova,
 		.destroy = msm_bo_destroy,
 };
 
diff --git a/freedreno/msm/msm_device.c b/freedreno/msm/msm_device.c
index 727baa4..7bb5767 100644
--- a/freedreno/msm/msm_device.c
+++ b/freedreno/msm/msm_device.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -64,5 +60,7 @@
 
 	fd_bo_cache_init(&msm_dev->ring_cache, TRUE);
 
+	dev->bo_size = sizeof(struct msm_bo);
+
 	return dev;
 }
diff --git a/freedreno/msm/msm_drm.h b/freedreno/msm/msm_drm.h
index ed4c8d4..dac49e5 100644
--- a/freedreno/msm/msm_drm.h
+++ b/freedreno/msm/msm_drm.h
@@ -73,6 +73,8 @@
 #define MSM_PARAM_CHIP_ID    0x03
 #define MSM_PARAM_MAX_FREQ   0x04
 #define MSM_PARAM_TIMESTAMP  0x05
+#define MSM_PARAM_GMEM_BASE  0x06
+#define MSM_PARAM_NR_RINGS   0x07
 
 struct drm_msm_param {
 	__u32 pipe;           /* in, MSM_PIPE_x */
@@ -104,10 +106,14 @@
 	__u32 handle;         /* out */
 };
 
+#define MSM_INFO_IOVA	0x01
+
+#define MSM_INFO_FLAGS (MSM_INFO_IOVA)
+
 struct drm_msm_gem_info {
 	__u32 handle;         /* in */
-	__u32 pad;
-	__u64 offset;         /* out, offset to pass to mmap() */
+	__u32 flags;	      /* in - combination of MSM_INFO_* flags */
+	__u64 offset;         /* out, mmap() offset or iova */
 };
 
 #define MSM_PREP_READ        0x01
@@ -167,7 +173,7 @@
 	__u32 size;           /* in, cmdstream size */
 	__u32 pad;
 	__u32 nr_relocs;      /* in, number of submit_reloc's */
-	__u64 __user relocs;  /* in, ptr to array of submit_reloc's */
+	__u64 relocs;         /* in, ptr to array of submit_reloc's */
 };
 
 /* Each buffer referenced elsewhere in the cmdstream submit (ie. the
@@ -211,9 +217,10 @@
 	__u32 fence;          /* out */
 	__u32 nr_bos;         /* in, number of submit_bo's */
 	__u32 nr_cmds;        /* in, number of submit_cmd's */
-	__u64 __user bos;     /* in, ptr to array of submit_bo's */
-	__u64 __user cmds;    /* in, ptr to array of submit_cmd's */
+	__u64 bos;            /* in, ptr to array of submit_bo's */
+	__u64 cmds;           /* in, ptr to array of submit_cmd's */
 	__s32 fence_fd;       /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */
+	__u32 queueid;         /* in, submitqueue id */
 };
 
 /* The normal way to synchronize with the GPU is just to CPU_PREP on
@@ -227,6 +234,7 @@
 	__u32 fence;          /* in */
 	__u32 pad;
 	struct drm_msm_timespec timeout;   /* in */
+	__u32 queueid;         /* in, submitqueue id */
 };
 
 /* madvise provides a way to tell the kernel in case a buffers contents
@@ -250,6 +258,20 @@
 	__u32 retained;       /* out, whether backing store still exists */
 };
 
+/*
+ * Draw queues allow the user to set specific submission parameter. Command
+ * submissions specify a specific submitqueue to use.  ID 0 is reserved for
+ * backwards compatibility as a "default" submitqueue
+ */
+
+#define MSM_SUBMITQUEUE_FLAGS (0)
+
+struct drm_msm_submitqueue {
+	__u32 flags;   /* in, MSM_SUBMITQUEUE_x */
+	__u32 prio;    /* in, Priority level */
+	__u32 id;      /* out, identifier */
+};
+
 #define DRM_MSM_GET_PARAM              0x00
 /* placeholder:
 #define DRM_MSM_SET_PARAM              0x01
@@ -261,7 +283,11 @@
 #define DRM_MSM_GEM_SUBMIT             0x06
 #define DRM_MSM_WAIT_FENCE             0x07
 #define DRM_MSM_GEM_MADVISE            0x08
-#define DRM_MSM_NUM_IOCTLS             0x09
+/* placeholder:
+#define DRM_MSM_GEM_SVM_NEW            0x09
+ */
+#define DRM_MSM_SUBMITQUEUE_NEW        0x0A
+#define DRM_MSM_SUBMITQUEUE_CLOSE      0x0B
 
 #define DRM_IOCTL_MSM_GET_PARAM        DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
 #define DRM_IOCTL_MSM_GEM_NEW          DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
@@ -271,6 +297,8 @@
 #define DRM_IOCTL_MSM_GEM_SUBMIT       DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_SUBMIT, struct drm_msm_gem_submit)
 #define DRM_IOCTL_MSM_WAIT_FENCE       DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_WAIT_FENCE, struct drm_msm_wait_fence)
 #define DRM_IOCTL_MSM_GEM_MADVISE      DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_MADVISE, struct drm_msm_gem_madvise)
+#define DRM_IOCTL_MSM_SUBMITQUEUE_NEW    DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_NEW, struct drm_msm_submitqueue)
+#define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE  DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32)
 
 #if defined(__cplusplus)
 }
diff --git a/freedreno/msm/msm_pipe.c b/freedreno/msm/msm_pipe.c
index f872e24..f28778e 100644
--- a/freedreno/msm/msm_pipe.c
+++ b/freedreno/msm/msm_pipe.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "msm_priv.h"
 
 static int query_param(struct fd_pipe *pipe, uint32_t param,
@@ -71,6 +67,8 @@
 		return query_param(pipe, MSM_PARAM_MAX_FREQ, value);
 	case FD_TIMESTAMP:
 		return query_param(pipe, MSM_PARAM_TIMESTAMP, value);
+	case FD_NR_RINGS:
+		return query_param(pipe, MSM_PARAM_NR_RINGS, value);
 	default:
 		ERROR_MSG("invalid param id: %d", param);
 		return -1;
@@ -83,6 +81,7 @@
 	struct fd_device *dev = pipe->dev;
 	struct drm_msm_wait_fence req = {
 			.fence = timestamp,
+			.queueid = to_msm_pipe(pipe)->queue_id,
 	};
 	int ret;
 
@@ -97,9 +96,48 @@
 	return 0;
 }
 
+static int open_submitqueue(struct fd_pipe *pipe, uint32_t prio)
+{
+	struct drm_msm_submitqueue req = {
+		.flags = 0,
+		.prio = prio,
+	};
+	uint64_t nr_rings = 1;
+	int ret;
+
+	if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES) {
+		to_msm_pipe(pipe)->queue_id = 0;
+		return 0;
+	}
+
+	msm_pipe_get_param(pipe, FD_NR_RINGS, &nr_rings);
+
+	req.prio = MIN2(req.prio, MAX2(nr_rings, 1) - 1);
+
+	ret = drmCommandWriteRead(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_NEW,
+			&req, sizeof(req));
+	if (ret) {
+		ERROR_MSG("could not create submitqueue! %d (%s)", ret, strerror(errno));
+		return ret;
+	}
+
+	to_msm_pipe(pipe)->queue_id = req.id;
+	return 0;
+}
+
+static void close_submitqueue(struct fd_pipe *pipe, uint32_t queue_id)
+{
+	if (fd_device_version(pipe->dev) < FD_VERSION_SUBMIT_QUEUES)
+		return;
+
+	drmCommandWrite(pipe->dev->fd, DRM_MSM_SUBMITQUEUE_CLOSE,
+			&queue_id, sizeof(queue_id));
+}
+
 static void msm_pipe_destroy(struct fd_pipe *pipe)
 {
 	struct msm_pipe *msm_pipe = to_msm_pipe(pipe);
+	close_submitqueue(pipe, msm_pipe->queue_id);
 	free(msm_pipe);
 }
 
@@ -122,7 +160,7 @@
 }
 
 drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev,
-		enum fd_pipe_id id)
+		enum fd_pipe_id id, uint32_t prio)
 {
 	static const uint32_t pipe_id[] = {
 			[FD_PIPE_3D] = MSM_PIPE_3D0,
@@ -157,6 +195,9 @@
 	INFO_MSG(" Chip-id:         0x%08x", msm_pipe->chip_id);
 	INFO_MSG(" GMEM size:       0x%08x", msm_pipe->gmem);
 
+	if (open_submitqueue(pipe, prio))
+		goto fail;
+
 	return pipe;
 fail:
 	if (pipe)
diff --git a/freedreno/msm/msm_priv.h b/freedreno/msm/msm_priv.h
index 6d670aa..88ac3aa 100644
--- a/freedreno/msm/msm_priv.h
+++ b/freedreno/msm/msm_priv.h
@@ -56,6 +56,7 @@
 	uint32_t gpu_id;
 	uint32_t gmem;
 	uint32_t chip_id;
+	uint32_t queue_id;
 };
 
 static inline struct msm_pipe * to_msm_pipe(struct fd_pipe *x)
@@ -64,7 +65,7 @@
 }
 
 drm_private struct fd_pipe * msm_pipe_new(struct fd_device *dev,
-		enum fd_pipe_id id);
+		enum fd_pipe_id id, uint32_t prio);
 
 drm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe,
 		uint32_t size);
diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c
index 17194f4..a87e1b9 100644
--- a/freedreno/msm/msm_ringbuffer.c
+++ b/freedreno/msm/msm_ringbuffer.c
@@ -26,10 +26,6 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <assert.h>
 #include <inttypes.h>
 
@@ -401,6 +397,7 @@
 	struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
 	struct drm_msm_gem_submit req = {
 			.flags = to_msm_pipe(ring->pipe)->pipe,
+			.queueid = to_msm_pipe(ring->pipe)->queue_id,
 	};
 	uint32_t i;
 	int ret;
@@ -496,11 +493,16 @@
 	if (ring->pipe->gpu_id >= 500) {
 		struct drm_msm_gem_submit_reloc *reloc_hi;
 
+		/* NOTE: grab reloc_idx *before* APPEND() since that could
+		 * realloc() meaning that 'reloc' ptr is no longer valid:
+		 */
+		uint32_t reloc_idx = reloc->reloc_idx;
+
 		idx = APPEND(cmd, relocs);
 
 		reloc_hi = &cmd->relocs[idx];
 
-		reloc_hi->reloc_idx = reloc->reloc_idx;
+		reloc_hi->reloc_idx = reloc_idx;
 		reloc_hi->reloc_offset = r->offset;
 		reloc_hi->or = r->orhi;
 		reloc_hi->shift = r->shift - 32;
@@ -584,12 +586,12 @@
 		uint32_t size)
 {
 	struct msm_ringbuffer *msm_ring;
-	struct fd_ringbuffer *ring = NULL;
+	struct fd_ringbuffer *ring;
 
 	msm_ring = calloc(1, sizeof(*msm_ring));
 	if (!msm_ring) {
 		ERROR_MSG("allocation failed");
-		goto fail;
+		return NULL;
 	}
 
 	if (size == 0) {
@@ -609,8 +611,4 @@
 	ring_cmd_new(ring, size);
 
 	return ring;
-fail:
-	if (ring)
-		fd_ringbuffer_del(ring);
-	return NULL;
 }
diff --git a/include/drm/README b/include/drm/README
index a50b02c..b4658dd 100644
--- a/include/drm/README
+++ b/include/drm/README
@@ -67,6 +67,8 @@
 
 When and how to update these files
 ----------------------------------
+Note: One should not do _any_ changes to the files apart from the steps below.
+
 In order to update the files do the following:
  - Switch to a Linux kernel tree/branch which is not rebased.
 For example: airlied/drm-next
@@ -84,47 +86,21 @@
 This section contains a list of headers and the respective "issues" they might
 have relative to their kernel equivalent.
 
-Nearly all headers:
- - Missing extern C notation.
-Status: Trivial.
-
 Most UMS headers:
  - Not using fixed size integers - compat ioctls are broken.
 Status: ?
 Promote to fixed size ints, which match the current (32bit) ones.
 
-
-amdgpu_drm.h
- - Using the stdint.h uint*_t over the respective __u* ones
-Status: Trivial.
-
-drm_mode.h
- - Missing DPI encode/connector pair.
-Status: Trivial.
-
-i915_drm.h
- - Missing PARAMS - HAS_POOLED_EU, MIN_EU_IN_POOL CONTEXT_PARAM_NO_ERROR_CAPTURE
-Status: Trivial.
-
-mga_drm.h
- - Typo fix, use struct over typedef.
-Status: Trivial.
-
 nouveau_drm.h
  - Missing macros NOUVEAU_GETPARAM*, NOUVEAU_DRM_HEADER_PATCHLEVEL, structs,
-enums, using stdint.h over the __u* types.
-Status: ?
-
-qxl_drm.h
- - Using the stdint.h uint*_t over the respective __u* ones
-Status: Trivial.
+enums
+Status: Deliberate UABI choice; nouveau hides the exact kernel ABI behind libdrm
 
 r128_drm.h
  - Broken compat ioctls.
 
 radeon_drm.h
- - Missing RADEON_TILING_R600_NO_SCANOUT, CIK_TILE_MODE_*, broken UMS ioctls,
-using stdint types.
+ - Missing RADEON_TILING_R600_NO_SCANOUT, CIK_TILE_MODE_*, broken UMS ioctls
  - Both kernel and libdrm: missing padding -
 drm_radeon_gem_{create,{g,s}et_tiling,set_domain} others ?
 Status: ?
diff --git a/include/drm/amdgpu_drm.h b/include/drm/amdgpu_drm.h
index d8f2497..c363b67 100644
--- a/include/drm/amdgpu_drm.h
+++ b/include/drm/amdgpu_drm.h
@@ -50,6 +50,10 @@
 #define DRM_AMDGPU_WAIT_CS		0x09
 #define DRM_AMDGPU_GEM_OP		0x10
 #define DRM_AMDGPU_GEM_USERPTR		0x11
+#define DRM_AMDGPU_WAIT_FENCES		0x12
+#define DRM_AMDGPU_VM			0x13
+#define DRM_AMDGPU_FENCE_TO_HANDLE	0x14
+#define DRM_AMDGPU_SCHED		0x15
 
 #define DRM_IOCTL_AMDGPU_GEM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
 #define DRM_IOCTL_AMDGPU_GEM_MMAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
@@ -63,6 +67,10 @@
 #define DRM_IOCTL_AMDGPU_WAIT_CS	DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs)
 #define DRM_IOCTL_AMDGPU_GEM_OP		DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op)
 #define DRM_IOCTL_AMDGPU_GEM_USERPTR	DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr)
+#define DRM_IOCTL_AMDGPU_WAIT_FENCES	DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences)
+#define DRM_IOCTL_AMDGPU_VM		DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm)
+#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle)
+#define DRM_IOCTL_AMDGPU_SCHED		DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched)
 
 #define AMDGPU_GEM_DOMAIN_CPU		0x1
 #define AMDGPU_GEM_DOMAIN_GTT		0x2
@@ -79,22 +87,30 @@
 #define AMDGPU_GEM_CREATE_CPU_GTT_USWC		(1 << 2)
 /* Flag that the memory should be in VRAM and cleared */
 #define AMDGPU_GEM_CREATE_VRAM_CLEARED		(1 << 3)
+/* Flag that create shadow bo(GTT) while allocating vram bo */
+#define AMDGPU_GEM_CREATE_SHADOW		(1 << 4)
+/* Flag that allocating the BO should use linear VRAM */
+#define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS	(1 << 5)
+/* Flag that BO is always valid in this VM */
+#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID	(1 << 6)
+/* Flag that BO sharing will be explicitly synchronized */
+#define AMDGPU_GEM_CREATE_EXPLICIT_SYNC		(1 << 7)
 
 struct drm_amdgpu_gem_create_in  {
 	/** the requested memory size */
-	uint64_t bo_size;
+	__u64 bo_size;
 	/** physical start_addr alignment in bytes for some HW requirements */
-	uint64_t alignment;
+	__u64 alignment;
 	/** the requested memory domains */
-	uint64_t domains;
+	__u64 domains;
 	/** allocation flags */
-	uint64_t domain_flags;
+	__u64 domain_flags;
 };
 
 struct drm_amdgpu_gem_create_out  {
 	/** returned GEM object handle */
-	uint32_t handle;
-	uint32_t _pad;
+	__u32 handle;
+	__u32 _pad;
 };
 
 union drm_amdgpu_gem_create {
@@ -111,28 +127,28 @@
 
 struct drm_amdgpu_bo_list_in {
 	/** Type of operation */
-	uint32_t operation;
+	__u32 operation;
 	/** Handle of list or 0 if we want to create one */
-	uint32_t list_handle;
+	__u32 list_handle;
 	/** Number of BOs in list  */
-	uint32_t bo_number;
+	__u32 bo_number;
 	/** Size of each element describing BO */
-	uint32_t bo_info_size;
+	__u32 bo_info_size;
 	/** Pointer to array describing BOs */
-	uint64_t bo_info_ptr;
+	__u64 bo_info_ptr;
 };
 
 struct drm_amdgpu_bo_list_entry {
 	/** Handle of BO */
-	uint32_t bo_handle;
+	__u32 bo_handle;
 	/** New (if specified) BO priority to be used during migration */
-	uint32_t bo_priority;
+	__u32 bo_priority;
 };
 
 struct drm_amdgpu_bo_list_out {
 	/** Handle of resource list  */
-	uint32_t list_handle;
-	uint32_t _pad;
+	__u32 list_handle;
+	__u32 _pad;
 };
 
 union drm_amdgpu_bo_list {
@@ -144,6 +160,7 @@
 #define AMDGPU_CTX_OP_ALLOC_CTX	1
 #define AMDGPU_CTX_OP_FREE_CTX	2
 #define AMDGPU_CTX_OP_QUERY_STATE	3
+#define AMDGPU_CTX_OP_QUERY_STATE2	4
 
 /* GPU reset status */
 #define AMDGPU_CTX_NO_RESET		0
@@ -154,28 +171,44 @@
 /* unknown cause */
 #define AMDGPU_CTX_UNKNOWN_RESET	3
 
+/* indicate gpu reset occured after ctx created */
+#define AMDGPU_CTX_QUERY2_FLAGS_RESET    (1<<0)
+/* indicate vram lost occured after ctx created */
+#define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1<<1)
+/* indicate some job from this context once cause gpu hang */
+#define AMDGPU_CTX_QUERY2_FLAGS_GUILTY   (1<<2)
+
+/* Context priority level */
+#define AMDGPU_CTX_PRIORITY_UNSET       -2048
+#define AMDGPU_CTX_PRIORITY_VERY_LOW    -1023
+#define AMDGPU_CTX_PRIORITY_LOW         -512
+#define AMDGPU_CTX_PRIORITY_NORMAL      0
+/* Selecting a priority above NORMAL requires CAP_SYS_NICE or DRM_MASTER */
+#define AMDGPU_CTX_PRIORITY_HIGH        512
+#define AMDGPU_CTX_PRIORITY_VERY_HIGH   1023
+
 struct drm_amdgpu_ctx_in {
 	/** AMDGPU_CTX_OP_* */
-	uint32_t	op;
+	__u32	op;
 	/** For future use, no flags defined so far */
-	uint32_t	flags;
-	uint32_t	ctx_id;
-	uint32_t	_pad;
+	__u32	flags;
+	__u32	ctx_id;
+	__s32	priority;
 };
 
 union drm_amdgpu_ctx_out {
 		struct {
-			uint32_t	ctx_id;
-			uint32_t	_pad;
+			__u32	ctx_id;
+			__u32	_pad;
 		} alloc;
 
 		struct {
 			/** For future use, no flags defined so far */
-			uint64_t	flags;
+			__u64	flags;
 			/** Number of resets caused by this context so far. */
-			uint32_t	hangs;
+			__u32	hangs;
 			/** Reset status since the last call of the ioctl. */
-			uint32_t	reset_status;
+			__u32	reset_status;
 		} state;
 };
 
@@ -184,6 +217,41 @@
 	union drm_amdgpu_ctx_out out;
 };
 
+/* vm ioctl */
+#define AMDGPU_VM_OP_RESERVE_VMID	1
+#define AMDGPU_VM_OP_UNRESERVE_VMID	2
+
+struct drm_amdgpu_vm_in {
+	/** AMDGPU_VM_OP_* */
+	__u32	op;
+	__u32	flags;
+};
+
+struct drm_amdgpu_vm_out {
+	/** For future use, no flags defined so far */
+	__u64	flags;
+};
+
+union drm_amdgpu_vm {
+	struct drm_amdgpu_vm_in in;
+	struct drm_amdgpu_vm_out out;
+};
+
+/* sched ioctl */
+#define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE	1
+
+struct drm_amdgpu_sched_in {
+	/* AMDGPU_SCHED_OP_* */
+	__u32	op;
+	__u32	fd;
+	__s32	priority;
+	__u32	flags;
+};
+
+union drm_amdgpu_sched {
+	struct drm_amdgpu_sched_in in;
+};
+
 /*
  * This is not a reliable API and you should expect it to fail for any
  * number of reasons and have fallback path that do not use userptr to
@@ -195,14 +263,15 @@
 #define AMDGPU_GEM_USERPTR_REGISTER	(1 << 3)
 
 struct drm_amdgpu_gem_userptr {
-	uint64_t		addr;
-	uint64_t		size;
+	__u64		addr;
+	__u64		size;
 	/* AMDGPU_GEM_USERPTR_* */
-	uint32_t		flags;
+	__u32		flags;
 	/* Resulting GEM handle */
-	uint32_t		handle;
+	__u32		handle;
 };
 
+/* SI-CI-VI: */
 /* same meaning as the GB_TILE_MODE and GL_MACRO_TILE_MODE fields */
 #define AMDGPU_TILING_ARRAY_MODE_SHIFT			0
 #define AMDGPU_TILING_ARRAY_MODE_MASK			0xf
@@ -221,10 +290,15 @@
 #define AMDGPU_TILING_NUM_BANKS_SHIFT			21
 #define AMDGPU_TILING_NUM_BANKS_MASK			0x3
 
+/* GFX9 and later: */
+#define AMDGPU_TILING_SWIZZLE_MODE_SHIFT		0
+#define AMDGPU_TILING_SWIZZLE_MODE_MASK			0x1f
+
+/* Set/Get helpers for tiling flags. */
 #define AMDGPU_TILING_SET(field, value) \
-	(((value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT)
+	(((__u64)(value) & AMDGPU_TILING_##field##_MASK) << AMDGPU_TILING_##field##_SHIFT)
 #define AMDGPU_TILING_GET(value, field) \
-	(((value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK)
+	(((__u64)(value) >> AMDGPU_TILING_##field##_SHIFT) & AMDGPU_TILING_##field##_MASK)
 
 #define AMDGPU_GEM_METADATA_OP_SET_METADATA                  1
 #define AMDGPU_GEM_METADATA_OP_GET_METADATA                  2
@@ -232,28 +306,28 @@
 /** The same structure is shared for input/output */
 struct drm_amdgpu_gem_metadata {
 	/** GEM Object handle */
-	uint32_t	handle;
+	__u32	handle;
 	/** Do we want get or set metadata */
-	uint32_t	op;
+	__u32	op;
 	struct {
 		/** For future use, no flags defined so far */
-		uint64_t	flags;
+		__u64	flags;
 		/** family specific tiling info */
-		uint64_t	tiling_info;
-		uint32_t	data_size_bytes;
-		uint32_t	data[64];
+		__u64	tiling_info;
+		__u32	data_size_bytes;
+		__u32	data[64];
 	} data;
 };
 
 struct drm_amdgpu_gem_mmap_in {
 	/** the GEM object handle */
-	uint32_t handle;
-	uint32_t _pad;
+	__u32 handle;
+	__u32 _pad;
 };
 
 struct drm_amdgpu_gem_mmap_out {
 	/** mmap offset from the vma offset manager */
-	uint64_t addr_ptr;
+	__u64 addr_ptr;
 };
 
 union drm_amdgpu_gem_mmap {
@@ -263,18 +337,18 @@
 
 struct drm_amdgpu_gem_wait_idle_in {
 	/** GEM object handle */
-	uint32_t handle;
+	__u32 handle;
 	/** For future use, no flags defined so far */
-	uint32_t flags;
+	__u32 flags;
 	/** Absolute timeout to wait */
-	uint64_t timeout;
+	__u64 timeout;
 };
 
 struct drm_amdgpu_gem_wait_idle_out {
 	/** BO status:  0 - BO is idle, 1 - BO is busy */
-	uint32_t status;
+	__u32 status;
 	/** Returned current memory domain */
-	uint32_t domain;
+	__u32 domain;
 };
 
 union drm_amdgpu_gem_wait_idle {
@@ -283,19 +357,22 @@
 };
 
 struct drm_amdgpu_wait_cs_in {
-	/** Command submission handle */
-	uint64_t handle;
+	/* Command submission handle
+         * handle equals 0 means none to wait for
+         * handle equals ~0ull means wait for the latest sequence number
+         */
+	__u64 handle;
 	/** Absolute timeout to wait */
-	uint64_t timeout;
-	uint32_t ip_type;
-	uint32_t ip_instance;
-	uint32_t ring;
-	uint32_t ctx_id;
+	__u64 timeout;
+	__u32 ip_type;
+	__u32 ip_instance;
+	__u32 ring;
+	__u32 ctx_id;
 };
 
 struct drm_amdgpu_wait_cs_out {
 	/** CS status:  0 - CS completed, 1 - CS still busy */
-	uint64_t status;
+	__u64 status;
 };
 
 union drm_amdgpu_wait_cs {
@@ -303,21 +380,49 @@
 	struct drm_amdgpu_wait_cs_out out;
 };
 
+struct drm_amdgpu_fence {
+	__u32 ctx_id;
+	__u32 ip_type;
+	__u32 ip_instance;
+	__u32 ring;
+	__u64 seq_no;
+};
+
+struct drm_amdgpu_wait_fences_in {
+	/** This points to uint64_t * which points to fences */
+	__u64 fences;
+	__u32 fence_count;
+	__u32 wait_all;
+	__u64 timeout_ns;
+};
+
+struct drm_amdgpu_wait_fences_out {
+	__u32 status;
+	__u32 first_signaled;
+};
+
+union drm_amdgpu_wait_fences {
+	struct drm_amdgpu_wait_fences_in in;
+	struct drm_amdgpu_wait_fences_out out;
+};
+
 #define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO	0
 #define AMDGPU_GEM_OP_SET_PLACEMENT		1
 
 /* Sets or returns a value associated with a buffer. */
 struct drm_amdgpu_gem_op {
 	/** GEM object handle */
-	uint32_t	handle;
+	__u32	handle;
 	/** AMDGPU_GEM_OP_* */
-	uint32_t	op;
+	__u32	op;
 	/** Input or return value */
-	uint64_t	value;
+	__u64	value;
 };
 
 #define AMDGPU_VA_OP_MAP			1
 #define AMDGPU_VA_OP_UNMAP			2
+#define AMDGPU_VA_OP_CLEAR			3
+#define AMDGPU_VA_OP_REPLACE			4
 
 /* Delay the page table update till the next CS */
 #define AMDGPU_VM_DELAY_UPDATE		(1 << 0)
@@ -329,21 +434,35 @@
 #define AMDGPU_VM_PAGE_WRITEABLE	(1 << 2)
 /* executable mapping, new for VI */
 #define AMDGPU_VM_PAGE_EXECUTABLE	(1 << 3)
+/* partially resident texture */
+#define AMDGPU_VM_PAGE_PRT		(1 << 4)
+/* MTYPE flags use bit 5 to 8 */
+#define AMDGPU_VM_MTYPE_MASK		(0xf << 5)
+/* Default MTYPE. Pre-AI must use this.  Recommended for newer ASICs. */
+#define AMDGPU_VM_MTYPE_DEFAULT		(0 << 5)
+/* Use NC MTYPE instead of default MTYPE */
+#define AMDGPU_VM_MTYPE_NC		(1 << 5)
+/* Use WC MTYPE instead of default MTYPE */
+#define AMDGPU_VM_MTYPE_WC		(2 << 5)
+/* Use CC MTYPE instead of default MTYPE */
+#define AMDGPU_VM_MTYPE_CC		(3 << 5)
+/* Use UC MTYPE instead of default MTYPE */
+#define AMDGPU_VM_MTYPE_UC		(4 << 5)
 
 struct drm_amdgpu_gem_va {
 	/** GEM object handle */
-	uint32_t handle;
-	uint32_t _pad;
+	__u32 handle;
+	__u32 _pad;
 	/** AMDGPU_VA_OP_* */
-	uint32_t operation;
+	__u32 operation;
 	/** AMDGPU_VM_PAGE_* */
-	uint32_t flags;
+	__u32 flags;
 	/** va address to assign . Must be correctly aligned.*/
-	uint64_t va_address;
+	__u64 va_address;
 	/** Specify offset inside of BO to assign. Must be correctly aligned.*/
-	uint64_t offset_in_bo;
+	__u64 offset_in_bo;
 	/** Specify mapping size. Must be correctly aligned. */
-	uint64_t map_size;
+	__u64 map_size;
 };
 
 #define AMDGPU_HW_IP_GFX          0
@@ -351,33 +470,38 @@
 #define AMDGPU_HW_IP_DMA          2
 #define AMDGPU_HW_IP_UVD          3
 #define AMDGPU_HW_IP_VCE          4
-#define AMDGPU_HW_IP_NUM          5
+#define AMDGPU_HW_IP_UVD_ENC      5
+#define AMDGPU_HW_IP_VCN_DEC      6
+#define AMDGPU_HW_IP_VCN_ENC      7
+#define AMDGPU_HW_IP_NUM          8
 
 #define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1
 
 #define AMDGPU_CHUNK_ID_IB		0x01
 #define AMDGPU_CHUNK_ID_FENCE		0x02
 #define AMDGPU_CHUNK_ID_DEPENDENCIES	0x03
+#define AMDGPU_CHUNK_ID_SYNCOBJ_IN      0x04
+#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT     0x05
 
 struct drm_amdgpu_cs_chunk {
-	uint32_t		chunk_id;
-	uint32_t		length_dw;
-	uint64_t		chunk_data;
+	__u32		chunk_id;
+	__u32		length_dw;
+	__u64		chunk_data;
 };
 
 struct drm_amdgpu_cs_in {
 	/** Rendering context id */
-	uint32_t		ctx_id;
+	__u32		ctx_id;
 	/**  Handle of resource list associated with CS */
-	uint32_t		bo_list_handle;
-	uint32_t		num_chunks;
-	uint32_t		_pad;
-	/** this points to uint64_t * which point to cs chunks */
-	uint64_t		chunks;
+	__u32		bo_list_handle;
+	__u32		num_chunks;
+	__u32		_pad;
+	/** this points to __u64 * which point to cs chunks */
+	__u64		chunks;
 };
 
 struct drm_amdgpu_cs_out {
-	uint64_t handle;
+	__u64 handle;
 };
 
 union drm_amdgpu_cs {
@@ -390,36 +514,58 @@
 /* This IB should be submitted to CE */
 #define AMDGPU_IB_FLAG_CE	(1<<0)
 
-/* CE Preamble */
+/* Preamble flag, which means the IB could be dropped if no context switch */
 #define AMDGPU_IB_FLAG_PREAMBLE (1<<1)
 
+/* Preempt flag, IB should set Pre_enb bit if PREEMPT flag detected */
+#define AMDGPU_IB_FLAG_PREEMPT (1<<2)
+
 struct drm_amdgpu_cs_chunk_ib {
-	uint32_t _pad;
+	__u32 _pad;
 	/** AMDGPU_IB_FLAG_* */
-	uint32_t flags;
+	__u32 flags;
 	/** Virtual address to begin IB execution */
-	uint64_t va_start;
+	__u64 va_start;
 	/** Size of submission */
-	uint32_t ib_bytes;
+	__u32 ib_bytes;
 	/** HW IP to submit to */
-	uint32_t ip_type;
+	__u32 ip_type;
 	/** HW IP index of the same type to submit to  */
-	uint32_t ip_instance;
+	__u32 ip_instance;
 	/** Ring index to submit to */
-	uint32_t ring;
+	__u32 ring;
 };
 
 struct drm_amdgpu_cs_chunk_dep {
-	uint32_t ip_type;
-	uint32_t ip_instance;
-	uint32_t ring;
-	uint32_t ctx_id;
-	uint64_t handle;
+	__u32 ip_type;
+	__u32 ip_instance;
+	__u32 ring;
+	__u32 ctx_id;
+	__u64 handle;
 };
 
 struct drm_amdgpu_cs_chunk_fence {
-	uint32_t handle;
-	uint32_t offset;
+	__u32 handle;
+	__u32 offset;
+};
+
+struct drm_amdgpu_cs_chunk_sem {
+	__u32 handle;
+};
+
+#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ	0
+#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD	1
+#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD	2
+
+union drm_amdgpu_fence_to_handle {
+	struct {
+		struct drm_amdgpu_fence fence;
+		__u32 what;
+		__u32 pad;
+	} in;
+	struct {
+		__u32 handle;
+	} out;
 };
 
 struct drm_amdgpu_cs_chunk_data {
@@ -434,6 +580,7 @@
  *
  */
 #define AMDGPU_IDS_FLAGS_FUSION         0x1
+#define AMDGPU_IDS_FLAGS_PREEMPTION     0x2
 
 /* indicate if acceleration can be working */
 #define AMDGPU_INFO_ACCEL_WORKING		0x00
@@ -467,6 +614,12 @@
 	#define AMDGPU_INFO_FW_SMC		0x0a
 	/* Subquery id: Query SDMA firmware version */
 	#define AMDGPU_INFO_FW_SDMA		0x0b
+	/* Subquery id: Query PSP SOS firmware version */
+	#define AMDGPU_INFO_FW_SOS		0x0c
+	/* Subquery id: Query PSP ASD firmware version */
+	#define AMDGPU_INFO_FW_ASD		0x0d
+	/* Subquery id: Query VCN firmware version */
+	#define AMDGPU_INFO_FW_VCN		0x0e
 /* number of bytes moved for TTM migration */
 #define AMDGPU_INFO_NUM_BYTES_MOVED		0x0f
 /* the used VRAM size */
@@ -483,6 +636,43 @@
 #define AMDGPU_INFO_DEV_INFO			0x16
 /* visible vram usage */
 #define AMDGPU_INFO_VIS_VRAM_USAGE		0x17
+/* number of TTM buffer evictions */
+#define AMDGPU_INFO_NUM_EVICTIONS		0x18
+/* Query memory about VRAM and GTT domains */
+#define AMDGPU_INFO_MEMORY			0x19
+/* Query vce clock table */
+#define AMDGPU_INFO_VCE_CLOCK_TABLE		0x1A
+/* Query vbios related information */
+#define AMDGPU_INFO_VBIOS			0x1B
+	/* Subquery id: Query vbios size */
+	#define AMDGPU_INFO_VBIOS_SIZE		0x1
+	/* Subquery id: Query vbios image */
+	#define AMDGPU_INFO_VBIOS_IMAGE		0x2
+/* Query UVD handles */
+#define AMDGPU_INFO_NUM_HANDLES			0x1C
+/* Query sensor related information */
+#define AMDGPU_INFO_SENSOR			0x1D
+	/* Subquery id: Query GPU shader clock */
+	#define AMDGPU_INFO_SENSOR_GFX_SCLK		0x1
+	/* Subquery id: Query GPU memory clock */
+	#define AMDGPU_INFO_SENSOR_GFX_MCLK		0x2
+	/* Subquery id: Query GPU temperature */
+	#define AMDGPU_INFO_SENSOR_GPU_TEMP		0x3
+	/* Subquery id: Query GPU load */
+	#define AMDGPU_INFO_SENSOR_GPU_LOAD		0x4
+	/* Subquery id: Query average GPU power	*/
+	#define AMDGPU_INFO_SENSOR_GPU_AVG_POWER	0x5
+	/* Subquery id: Query northbridge voltage */
+	#define AMDGPU_INFO_SENSOR_VDDNB		0x6
+	/* Subquery id: Query graphics voltage */
+	#define AMDGPU_INFO_SENSOR_VDDGFX		0x7
+	/* Subquery id: Query GPU stable pstate shader clock */
+	#define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_SCLK		0x8
+	/* Subquery id: Query GPU stable pstate memory clock */
+	#define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK		0x9
+/* Number of VRAM page faults on CPU access. */
+#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS	0x1E
+#define AMDGPU_INFO_VRAM_LOST_COUNTER		0x1F
 
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT	0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK	0xff
@@ -491,86 +681,123 @@
 
 struct drm_amdgpu_query_fw {
 	/** AMDGPU_INFO_FW_* */
-	uint32_t fw_type;
+	__u32 fw_type;
 	/**
 	 * Index of the IP if there are more IPs of
 	 * the same type.
 	 */
-	uint32_t ip_instance;
+	__u32 ip_instance;
 	/**
 	 * Index of the engine. Whether this is used depends
 	 * on the firmware type. (e.g. MEC, SDMA)
 	 */
-	uint32_t index;
-	uint32_t _pad;
+	__u32 index;
+	__u32 _pad;
 };
 
 /* Input structure for the INFO ioctl */
 struct drm_amdgpu_info {
 	/* Where the return value will be stored */
-	uint64_t return_pointer;
+	__u64 return_pointer;
 	/* The size of the return value. Just like "size" in "snprintf",
 	 * it limits how many bytes the kernel can write. */
-	uint32_t return_size;
+	__u32 return_size;
 	/* The query request id. */
-	uint32_t query;
+	__u32 query;
 
 	union {
 		struct {
-			uint32_t id;
-			uint32_t _pad;
+			__u32 id;
+			__u32 _pad;
 		} mode_crtc;
 
 		struct {
 			/** AMDGPU_HW_IP_* */
-			uint32_t type;
+			__u32 type;
 			/**
 			 * Index of the IP if there are more IPs of the same
 			 * type. Ignored by AMDGPU_INFO_HW_IP_COUNT.
 			 */
-			uint32_t ip_instance;
+			__u32 ip_instance;
 		} query_hw_ip;
 
 		struct {
-			uint32_t dword_offset;
+			__u32 dword_offset;
 			/** number of registers to read */
-			uint32_t count;
-			uint32_t instance;
+			__u32 count;
+			__u32 instance;
 			/** For future use, no flags defined so far */
-			uint32_t flags;
+			__u32 flags;
 		} read_mmr_reg;
 
 		struct drm_amdgpu_query_fw query_fw;
+
+		struct {
+			__u32 type;
+			__u32 offset;
+		} vbios_info;
+
+		struct {
+			__u32 type;
+		} sensor_info;
 	};
 };
 
 struct drm_amdgpu_info_gds {
 	/** GDS GFX partition size */
-	uint32_t gds_gfx_partition_size;
+	__u32 gds_gfx_partition_size;
 	/** GDS compute partition size */
-	uint32_t compute_partition_size;
+	__u32 compute_partition_size;
 	/** total GDS memory size */
-	uint32_t gds_total_size;
+	__u32 gds_total_size;
 	/** GWS size per GFX partition */
-	uint32_t gws_per_gfx_partition;
+	__u32 gws_per_gfx_partition;
 	/** GSW size per compute partition */
-	uint32_t gws_per_compute_partition;
+	__u32 gws_per_compute_partition;
 	/** OA size per GFX partition */
-	uint32_t oa_per_gfx_partition;
+	__u32 oa_per_gfx_partition;
 	/** OA size per compute partition */
-	uint32_t oa_per_compute_partition;
-	uint32_t _pad;
+	__u32 oa_per_compute_partition;
+	__u32 _pad;
 };
 
 struct drm_amdgpu_info_vram_gtt {
-	uint64_t vram_size;
-	uint64_t vram_cpu_accessible_size;
-	uint64_t gtt_size;
+	__u64 vram_size;
+	__u64 vram_cpu_accessible_size;
+	__u64 gtt_size;
+};
+
+struct drm_amdgpu_heap_info {
+	/** max. physical memory */
+	__u64 total_heap_size;
+
+	/** Theoretical max. available memory in the given heap */
+	__u64 usable_heap_size;
+
+	/**
+	 * Number of bytes allocated in the heap. This includes all processes
+	 * and private allocations in the kernel. It changes when new buffers
+	 * are allocated, freed, and moved. It cannot be larger than
+	 * heap_size.
+	 */
+	__u64 heap_usage;
+
+	/**
+	 * Theoretical possible max. size of buffer which
+	 * could be allocated in the given heap
+	 */
+	__u64 max_allocation;
+};
+
+struct drm_amdgpu_memory_info {
+	struct drm_amdgpu_heap_info vram;
+	struct drm_amdgpu_heap_info cpu_accessible_vram;
+	struct drm_amdgpu_heap_info gtt;
 };
 
 struct drm_amdgpu_info_firmware {
-	uint32_t ver;
-	uint32_t feature;
+	__u32 ver;
+	__u32 feature;
 };
 
 #define AMDGPU_VRAM_TYPE_UNKNOWN 0
@@ -581,74 +808,139 @@
 #define AMDGPU_VRAM_TYPE_GDDR5 5
 #define AMDGPU_VRAM_TYPE_HBM   6
 #define AMDGPU_VRAM_TYPE_DDR3  7
+#define AMDGPU_VRAM_TYPE_DDR4  8
 
 struct drm_amdgpu_info_device {
 	/** PCI Device ID */
-	uint32_t device_id;
+	__u32 device_id;
 	/** Internal chip revision: A0, A1, etc.) */
-	uint32_t chip_rev;
-	uint32_t external_rev;
+	__u32 chip_rev;
+	__u32 external_rev;
 	/** Revision id in PCI Config space */
-	uint32_t pci_rev;
-	uint32_t family;
-	uint32_t num_shader_engines;
-	uint32_t num_shader_arrays_per_engine;
+	__u32 pci_rev;
+	__u32 family;
+	__u32 num_shader_engines;
+	__u32 num_shader_arrays_per_engine;
 	/* in KHz */
-	uint32_t gpu_counter_freq;
-	uint64_t max_engine_clock;
-	uint64_t max_memory_clock;
+	__u32 gpu_counter_freq;
+	__u64 max_engine_clock;
+	__u64 max_memory_clock;
 	/* cu information */
-	uint32_t cu_active_number;
-	uint32_t cu_ao_mask;
-	uint32_t cu_bitmap[4][4];
+	__u32 cu_active_number;
+	/* NOTE: cu_ao_mask is INVALID, DON'T use it */
+	__u32 cu_ao_mask;
+	__u32 cu_bitmap[4][4];
 	/** Render backend pipe mask. One render backend is CB+DB. */
-	uint32_t enabled_rb_pipes_mask;
-	uint32_t num_rb_pipes;
-	uint32_t num_hw_gfx_contexts;
-	uint32_t _pad;
-	uint64_t ids_flags;
+	__u32 enabled_rb_pipes_mask;
+	__u32 num_rb_pipes;
+	__u32 num_hw_gfx_contexts;
+	__u32 _pad;
+	__u64 ids_flags;
 	/** Starting virtual address for UMDs. */
-	uint64_t virtual_address_offset;
+	__u64 virtual_address_offset;
 	/** The maximum virtual address */
-	uint64_t virtual_address_max;
+	__u64 virtual_address_max;
 	/** Required alignment of virtual addresses. */
-	uint32_t virtual_address_alignment;
+	__u32 virtual_address_alignment;
 	/** Page table entry - fragment size */
-	uint32_t pte_fragment_size;
-	uint32_t gart_page_size;
+	__u32 pte_fragment_size;
+	__u32 gart_page_size;
 	/** constant engine ram size*/
-	uint32_t ce_ram_size;
+	__u32 ce_ram_size;
 	/** video memory type info*/
-	uint32_t vram_type;
+	__u32 vram_type;
 	/** video memory bit width*/
-	uint32_t vram_bit_width;
+	__u32 vram_bit_width;
 	/* vce harvesting instance */
-	uint32_t vce_harvest_config;
+	__u32 vce_harvest_config;
+	/* gfx double offchip LDS buffers */
+	__u32 gc_double_offchip_lds_buf;
+	/* NGG Primitive Buffer */
+	__u64 prim_buf_gpu_addr;
+	/* NGG Position Buffer */
+	__u64 pos_buf_gpu_addr;
+	/* NGG Control Sideband */
+	__u64 cntl_sb_buf_gpu_addr;
+	/* NGG Parameter Cache */
+	__u64 param_buf_gpu_addr;
+	__u32 prim_buf_size;
+	__u32 pos_buf_size;
+	__u32 cntl_sb_buf_size;
+	__u32 param_buf_size;
+	/* wavefront size*/
+	__u32 wave_front_size;
+	/* shader visible vgprs*/
+	__u32 num_shader_visible_vgprs;
+	/* CU per shader array*/
+	__u32 num_cu_per_sh;
+	/* number of tcc blocks*/
+	__u32 num_tcc_blocks;
+	/* gs vgt table depth*/
+	__u32 gs_vgt_table_depth;
+	/* gs primitive buffer depth*/
+	__u32 gs_prim_buffer_depth;
+	/* max gs wavefront per vgt*/
+	__u32 max_gs_waves_per_vgt;
+	__u32 _pad1;
+	/* always on cu bitmap */
+	__u32 cu_ao_bitmap[4][4];
+	/** Starting high virtual address for UMDs. */
+	__u64 high_va_offset;
+	/** The maximum high virtual address */
+	__u64 high_va_max;
 };
 
 struct drm_amdgpu_info_hw_ip {
 	/** Version of h/w IP */
-	uint32_t  hw_ip_version_major;
-	uint32_t  hw_ip_version_minor;
+	__u32  hw_ip_version_major;
+	__u32  hw_ip_version_minor;
 	/** Capabilities */
-	uint64_t  capabilities_flags;
+	__u64  capabilities_flags;
 	/** command buffer address start alignment*/
-	uint32_t  ib_start_alignment;
+	__u32  ib_start_alignment;
 	/** command buffer size alignment*/
-	uint32_t  ib_size_alignment;
+	__u32  ib_size_alignment;
 	/** Bitmask of available rings. Bit 0 means ring 0, etc. */
-	uint32_t  available_rings;
-	uint32_t  _pad;
+	__u32  available_rings;
+	__u32  _pad;
+};
+
+struct drm_amdgpu_info_num_handles {
+	/** Max handles as supported by firmware for UVD */
+	__u32  uvd_max_handles;
+	/** Handles currently in use for UVD */
+	__u32  uvd_used_handles;
+};
+
+#define AMDGPU_VCE_CLOCK_TABLE_ENTRIES		6
+
+struct drm_amdgpu_info_vce_clock_table_entry {
+	/** System clock */
+	__u32 sclk;
+	/** Memory clock */
+	__u32 mclk;
+	/** VCE clock */
+	__u32 eclk;
+	__u32 pad;
+};
+
+struct drm_amdgpu_info_vce_clock_table {
+	struct drm_amdgpu_info_vce_clock_table_entry entries[AMDGPU_VCE_CLOCK_TABLE_ENTRIES];
+	__u32 num_valid_entries;
+	__u32 pad;
 };
 
 /*
  * Supported GPU families
  */
 #define AMDGPU_FAMILY_UNKNOWN			0
+#define AMDGPU_FAMILY_SI			110 /* Hainan, Oland, Verde, Pitcairn, Tahiti */
 #define AMDGPU_FAMILY_CI			120 /* Bonaire, Hawaii */
 #define AMDGPU_FAMILY_KV			125 /* Kaveri, Kabini, Mullins */
 #define AMDGPU_FAMILY_VI			130 /* Iceland, Tonga */
 #define AMDGPU_FAMILY_CZ			135 /* Carrizo, Stoney */
+#define AMDGPU_FAMILY_AI			141 /* Vega10 */
+#define AMDGPU_FAMILY_RV			142 /* Raven */
 
 #if defined(__cplusplus)
 }
diff --git a/include/drm/drm.h b/include/drm/drm.h
index f6fd5c2..f0bd91d 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -641,6 +641,8 @@
 #define DRM_CAP_CURSOR_HEIGHT		0x9
 #define DRM_CAP_ADDFB2_MODIFIERS	0x10
 #define DRM_CAP_PAGE_FLIP_TARGET	0x11
+#define DRM_CAP_CRTC_IN_VBLANK_EVENT	0x12
+#define DRM_CAP_SYNCOBJ		0x13
 
 /** DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
@@ -690,6 +692,67 @@
 	__s32 fd;
 };
 
+struct drm_syncobj_create {
+	__u32 handle;
+#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0)
+	__u32 flags;
+};
+
+struct drm_syncobj_destroy {
+	__u32 handle;
+	__u32 pad;
+};
+
+#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0)
+#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0)
+struct drm_syncobj_handle {
+	__u32 handle;
+	__u32 flags;
+
+	__s32 fd;
+	__u32 pad;
+};
+
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+struct drm_syncobj_wait {
+	__u64 handles;
+	/* absolute timeout */
+	__s64 timeout_nsec;
+	__u32 count_handles;
+	__u32 flags;
+	__u32 first_signaled; /* only valid when not waiting all */
+	__u32 pad;
+};
+
+struct drm_syncobj_array {
+	__u64 handles;
+	__u32 count_handles;
+	__u32 pad;
+};
+
+/* Query current scanout sequence number */
+struct drm_crtc_get_sequence {
+	__u32 crtc_id;		/* requested crtc_id */
+	__u32 active;		/* return: crtc output is active */
+	__u64 sequence;		/* return: most recent vblank sequence */
+	__s64 sequence_ns;	/* return: most recent time of first pixel out */
+};
+
+/* Queue event to be delivered at specified sequence. Time stamp marks
+ * when the first pixel of the refresh cycle leaves the display engine
+ * for the display
+ */
+#define DRM_CRTC_SEQUENCE_RELATIVE		0x00000001	/* sequence is relative to current */
+#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS		0x00000002	/* Use next sequence if we've missed */
+
+struct drm_crtc_queue_sequence {
+	__u32 crtc_id;
+	__u32 flags;
+	__u64 sequence;		/* on input, target sequence. on output, actual sequence */
+	__u64 user_data;	/* user data passed to event */
+};
+
 #if defined(__cplusplus)
 }
 #endif
@@ -772,6 +835,9 @@
 
 #define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, union drm_wait_vblank)
 
+#define DRM_IOCTL_CRTC_GET_SEQUENCE	DRM_IOWR(0x3b, struct drm_crtc_get_sequence)
+#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE	DRM_IOWR(0x3c, struct drm_crtc_queue_sequence)
+
 #define DRM_IOCTL_UPDATE_DRAW		DRM_IOW(0x3f, struct drm_update_draw)
 
 #define DRM_IOCTL_MODE_GETRESOURCES	DRM_IOWR(0xA0, struct drm_mode_card_res)
@@ -808,6 +874,19 @@
 #define DRM_IOCTL_MODE_CREATEPROPBLOB	DRM_IOWR(0xBD, struct drm_mode_create_blob)
 #define DRM_IOCTL_MODE_DESTROYPROPBLOB	DRM_IOWR(0xBE, struct drm_mode_destroy_blob)
 
+#define DRM_IOCTL_SYNCOBJ_CREATE	DRM_IOWR(0xBF, struct drm_syncobj_create)
+#define DRM_IOCTL_SYNCOBJ_DESTROY	DRM_IOWR(0xC0, struct drm_syncobj_destroy)
+#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD	DRM_IOWR(0xC1, struct drm_syncobj_handle)
+#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE	DRM_IOWR(0xC2, struct drm_syncobj_handle)
+#define DRM_IOCTL_SYNCOBJ_WAIT		DRM_IOWR(0xC3, struct drm_syncobj_wait)
+#define DRM_IOCTL_SYNCOBJ_RESET		DRM_IOWR(0xC4, struct drm_syncobj_array)
+#define DRM_IOCTL_SYNCOBJ_SIGNAL	DRM_IOWR(0xC5, struct drm_syncobj_array)
+
+#define DRM_IOCTL_MODE_CREATE_LEASE	DRM_IOWR(0xC6, struct drm_mode_create_lease)
+#define DRM_IOCTL_MODE_LIST_LESSEES	DRM_IOWR(0xC7, struct drm_mode_list_lessees)
+#define DRM_IOCTL_MODE_GET_LEASE	DRM_IOWR(0xC8, struct drm_mode_get_lease)
+#define DRM_IOCTL_MODE_REVOKE_LEASE	DRM_IOWR(0xC9, struct drm_mode_revoke_lease)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
@@ -838,6 +917,7 @@
 
 #define DRM_EVENT_VBLANK 0x01
 #define DRM_EVENT_FLIP_COMPLETE 0x02
+#define DRM_EVENT_CRTC_SEQUENCE	0x03
 
 struct drm_event_vblank {
 	struct drm_event base;
@@ -845,7 +925,17 @@
 	__u32 tv_sec;
 	__u32 tv_usec;
 	__u32 sequence;
-	__u32 reserved;
+	__u32 crtc_id; /* 0 on older kernels that do not support this */
+};
+
+/* Event delivered at sequence. Time stamp marks when the first pixel
+ * of the refresh cycle leaves the display engine for the display
+ */
+struct drm_event_crtc_sequence {
+	struct drm_event	base;
+	__u64			user_data;
+	__s64			time_ns;
+	__u64			sequence;
 };
 
 /* typedef area */
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 4d8da69..e04613d 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -26,6 +26,10 @@
 
 #include "drm.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 #define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
 				 ((__u32)(c) << 16) | ((__u32)(d) << 24))
 
@@ -37,10 +41,17 @@
 /* 8 bpp Red */
 #define DRM_FORMAT_R8		fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
 
+/* 16 bpp Red */
+#define DRM_FORMAT_R16		fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */
+
 /* 16 bpp RG */
 #define DRM_FORMAT_RG88		fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */
 #define DRM_FORMAT_GR88		fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */
 
+/* 32 bpp RG */
+#define DRM_FORMAT_RG1616	fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */
+#define DRM_FORMAT_GR1616	fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */
+
 /* 8 bpp RGB */
 #define DRM_FORMAT_RGB332	fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */
 #define DRM_FORMAT_BGR233	fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */
@@ -103,6 +114,20 @@
 #define DRM_FORMAT_AYUV		fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
 
 /*
+ * 2 plane RGB + A
+ * index 0 = RGB plane, same format as the corresponding non _A8 format has
+ * index 1 = A plane, [7:0] A
+ */
+#define DRM_FORMAT_XRGB8888_A8	fourcc_code('X', 'R', 'A', '8')
+#define DRM_FORMAT_XBGR8888_A8	fourcc_code('X', 'B', 'A', '8')
+#define DRM_FORMAT_RGBX8888_A8	fourcc_code('R', 'X', 'A', '8')
+#define DRM_FORMAT_BGRX8888_A8	fourcc_code('B', 'X', 'A', '8')
+#define DRM_FORMAT_RGB888_A8	fourcc_code('R', '8', 'A', '8')
+#define DRM_FORMAT_BGR888_A8	fourcc_code('B', '8', 'A', '8')
+#define DRM_FORMAT_RGB565_A8	fourcc_code('R', '5', 'A', '8')
+#define DRM_FORMAT_BGR565_A8	fourcc_code('B', '5', 'A', '8')
+
+/*
  * 2 plane YCbCr
  * index 0 = Y plane, [7:0] Y
  * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
@@ -150,15 +175,20 @@
 
 /* Vendor Ids: */
 #define DRM_FORMAT_MOD_NONE           0
+#define DRM_FORMAT_MOD_VENDOR_NONE    0
 #define DRM_FORMAT_MOD_VENDOR_INTEL   0x01
 #define DRM_FORMAT_MOD_VENDOR_AMD     0x02
-#define DRM_FORMAT_MOD_VENDOR_NV      0x03
+#define DRM_FORMAT_MOD_VENDOR_NVIDIA  0x03
 #define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04
 #define DRM_FORMAT_MOD_VENDOR_QCOM    0x05
+#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
+#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
 /* add more to the end as needed */
 
+#define DRM_FORMAT_RESERVED	      ((1ULL << 56) - 1)
+
 #define fourcc_mod_code(vendor, val) \
-	((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
+	((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
 
 /*
  * Format Modifier tokens:
@@ -168,6 +198,25 @@
  * authoritative source for all of these.
  */
 
+/*
+ * Invalid Modifier
+ *
+ * This modifier can be used as a sentinel to terminate the format modifiers
+ * list, or to initialize a variable with an invalid modifier. It might also be
+ * used to report an error back to userspace for certain APIs.
+ */
+#define DRM_FORMAT_MOD_INVALID	fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
+
+/*
+ * Linear Layout
+ *
+ * Just plain linear layout. Note that this is different from no specifying any
+ * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl),
+ * which tells the driver to also take driver-internal information into account
+ * and so might actually result in a tiled framebuffer.
+ */
+#define DRM_FORMAT_MOD_LINEAR	fourcc_mod_code(NONE, 0)
+
 /* Intel framebuffer modifiers */
 
 /*
@@ -215,6 +264,26 @@
 #define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3)
 
 /*
+ * Intel color control surface (CCS) for render compression
+ *
+ * The framebuffer format must be one of the 8:8:8:8 RGB formats.
+ * The main surface will be plane index 0 and must be Y/Yf-tiled,
+ * the CCS will be plane index 1.
+ *
+ * Each CCS tile matches a 1024x512 pixel area of the main surface.
+ * To match certain aspects of the 3D hardware the CCS is
+ * considered to be made up of normal 128Bx32 Y tiles, Thus
+ * the CCS pitch must be specified in multiples of 128 bytes.
+ *
+ * In reality the CCS tile appears to be a 64Bx64 Y tile, composed
+ * of QWORD (8 bytes) chunks instead of OWORD (16 bytes) chunks.
+ * But that fact is not relevant unless the memory is accessed
+ * directly.
+ */
+#define I915_FORMAT_MOD_Y_TILED_CCS	fourcc_mod_code(INTEL, 4)
+#define I915_FORMAT_MOD_Yf_TILED_CCS	fourcc_mod_code(INTEL, 5)
+
+/*
  * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks
  *
  * Macroblocks are laid in a Z-shape, and each pixel data is following the
@@ -229,4 +298,115 @@
  */
 #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE	fourcc_mod_code(SAMSUNG, 1)
 
+/* Vivante framebuffer modifiers */
+
+/*
+ * Vivante 4x4 tiling layout
+ *
+ * This is a simple tiled layout using tiles of 4x4 pixels in a row-major
+ * layout.
+ */
+#define DRM_FORMAT_MOD_VIVANTE_TILED		fourcc_mod_code(VIVANTE, 1)
+
+/*
+ * Vivante 64x64 super-tiling layout
+ *
+ * This is a tiled layout using 64x64 pixel super-tiles, where each super-tile
+ * contains 8x4 groups of 2x4 tiles of 4x4 pixels (like above) each, all in row-
+ * major layout.
+ *
+ * For more information: see
+ * https://github.com/etnaviv/etna_viv/blob/master/doc/hardware.md#texture-tiling
+ */
+#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED	fourcc_mod_code(VIVANTE, 2)
+
+/*
+ * Vivante 4x4 tiling layout for dual-pipe
+ *
+ * Same as the 4x4 tiling layout, except every second 4x4 pixel tile starts at a
+ * different base address. Offsets from the base addresses are therefore halved
+ * compared to the non-split tiled layout.
+ */
+#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED	fourcc_mod_code(VIVANTE, 3)
+
+/*
+ * Vivante 64x64 super-tiling layout for dual-pipe
+ *
+ * Same as the 64x64 super-tiling layout, except every second 4x4 pixel tile
+ * starts at a different base address. Offsets from the base addresses are
+ * therefore halved compared to the non-split super-tiled layout.
+ */
+#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)
+
+/* NVIDIA frame buffer modifiers */
+
+/*
+ * Tegra Tiled Layout, used by Tegra 2, 3 and 4.
+ *
+ * Pixels are arranged in simple tiles of 16 x 16 bytes.
+ */
+#define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1)
+
+/*
+ * 16Bx2 Block Linear layout, used by desktop GPUs, and Tegra K1 and later
+ *
+ * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked
+ * vertically by a power of 2 (1 to 32 GOBs) to form a block.
+ *
+ * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape.
+ *
+ * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically.
+ * Valid values are:
+ *
+ * 0 == ONE_GOB
+ * 1 == TWO_GOBS
+ * 2 == FOUR_GOBS
+ * 3 == EIGHT_GOBS
+ * 4 == SIXTEEN_GOBS
+ * 5 == THIRTYTWO_GOBS
+ *
+ * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format
+ * in full detail.
+ */
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) \
+	fourcc_mod_code(NVIDIA, 0x10 | ((v) & 0xf))
+
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB \
+	fourcc_mod_code(NVIDIA, 0x10)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB \
+	fourcc_mod_code(NVIDIA, 0x11)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB \
+	fourcc_mod_code(NVIDIA, 0x12)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB \
+	fourcc_mod_code(NVIDIA, 0x13)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB \
+	fourcc_mod_code(NVIDIA, 0x14)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \
+	fourcc_mod_code(NVIDIA, 0x15)
+
+/*
+ * Broadcom VC4 "T" format
+ *
+ * This is the primary layout that the V3D GPU can texture from (it
+ * can't do linear).  The T format has:
+ *
+ * - 64b utiles of pixels in a raster-order grid according to cpp.  It's 4x4
+ *   pixels at 32 bit depth.
+ *
+ * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually
+ *   16x16 pixels).
+ *
+ * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels).  On
+ *   even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows
+ *   they're (TR, BR, BL, TL), where bottom left is start of memory.
+ *
+ * - an image made of 4k tiles in rows either left-to-right (even rows of 4k
+ *   tiles) or right-to-left (odd rows of 4k tiles).
+ */
+#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
+
+#if defined(__cplusplus)
+}
+#endif
+
 #endif /* DRM_FOURCC_H */
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 6708e2b..74368de 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -38,16 +38,24 @@
 #define DRM_DISPLAY_MODE_LEN	32
 #define DRM_PROP_NAME_LEN	32
 
-#define DRM_MODE_TYPE_BUILTIN	(1<<0)
-#define DRM_MODE_TYPE_CLOCK_C	((1<<1) | DRM_MODE_TYPE_BUILTIN)
-#define DRM_MODE_TYPE_CRTC_C	((1<<2) | DRM_MODE_TYPE_BUILTIN)
+#define DRM_MODE_TYPE_BUILTIN	(1<<0) /* deprecated */
+#define DRM_MODE_TYPE_CLOCK_C	((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */
+#define DRM_MODE_TYPE_CRTC_C	((1<<2) | DRM_MODE_TYPE_BUILTIN) /* deprecated */
 #define DRM_MODE_TYPE_PREFERRED	(1<<3)
-#define DRM_MODE_TYPE_DEFAULT	(1<<4)
+#define DRM_MODE_TYPE_DEFAULT	(1<<4) /* deprecated */
 #define DRM_MODE_TYPE_USERDEF	(1<<5)
 #define DRM_MODE_TYPE_DRIVER	(1<<6)
 
 /* Video mode flags */
-/* bit compatible with the xorg definitions. */
+/* bit compatible with the xrandr RR_ definitions (bits 0-13)
+ *
+ * ABI warning: Existing userspace really expects
+ * the mode flags to match the xrandr definitions. Any
+ * changes that don't match the xrandr definitions will
+ * likely need a new client cap or some other mechanism
+ * to avoid breaking existing userspace. This includes
+ * allocating new flags in the previously unused bits!
+ */
 #define DRM_MODE_FLAG_PHSYNC			(1<<0)
 #define DRM_MODE_FLAG_NHSYNC			(1<<1)
 #define DRM_MODE_FLAG_PVSYNC			(1<<2)
@@ -58,8 +66,8 @@
 #define DRM_MODE_FLAG_PCSYNC			(1<<7)
 #define DRM_MODE_FLAG_NCSYNC			(1<<8)
 #define DRM_MODE_FLAG_HSKEW			(1<<9) /* hskew provided */
-#define DRM_MODE_FLAG_BCAST			(1<<10)
-#define DRM_MODE_FLAG_PIXMUX			(1<<11)
+#define DRM_MODE_FLAG_BCAST			(1<<10) /* deprecated */
+#define DRM_MODE_FLAG_PIXMUX			(1<<11) /* deprecated */
 #define DRM_MODE_FLAG_DBLCLK			(1<<12)
 #define DRM_MODE_FLAG_CLKDIV2			(1<<13)
  /*
@@ -67,7 +75,7 @@
   * (define not exposed to user space).
   */
 #define DRM_MODE_FLAG_3D_MASK			(0x1f<<14)
-#define  DRM_MODE_FLAG_3D_NONE			(0<<14)
+#define  DRM_MODE_FLAG_3D_NONE		(0<<14)
 #define  DRM_MODE_FLAG_3D_FRAME_PACKING		(1<<14)
 #define  DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE	(2<<14)
 #define  DRM_MODE_FLAG_3D_LINE_ALTERNATIVE	(3<<14)
@@ -77,6 +85,19 @@
 #define  DRM_MODE_FLAG_3D_TOP_AND_BOTTOM	(7<<14)
 #define  DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF	(8<<14)
 
+/* Picture aspect ratio options */
+#define DRM_MODE_PICTURE_ASPECT_NONE		0
+#define DRM_MODE_PICTURE_ASPECT_4_3		1
+#define DRM_MODE_PICTURE_ASPECT_16_9		2
+
+/* Aspect ratio flag bitmask (4 bits 22:19) */
+#define DRM_MODE_FLAG_PIC_AR_MASK		(0x0F<<19)
+#define  DRM_MODE_FLAG_PIC_AR_NONE \
+			(DRM_MODE_PICTURE_ASPECT_NONE<<19)
+#define  DRM_MODE_FLAG_PIC_AR_4_3 \
+			(DRM_MODE_PICTURE_ASPECT_4_3<<19)
+#define  DRM_MODE_FLAG_PIC_AR_16_9 \
+			(DRM_MODE_PICTURE_ASPECT_16_9<<19)
 
 /* DPMS flags */
 /* bit compatible with the xorg definitions. */
@@ -92,11 +113,6 @@
 #define DRM_MODE_SCALE_CENTER		2 /* Centered, no scaling */
 #define DRM_MODE_SCALE_ASPECT		3 /* Full screen, preserve aspect */
 
-/* Picture aspect ratio options */
-#define DRM_MODE_PICTURE_ASPECT_NONE	0
-#define DRM_MODE_PICTURE_ASPECT_4_3	1
-#define DRM_MODE_PICTURE_ASPECT_16_9	2
-
 /* Dithering mode options */
 #define DRM_MODE_DITHERING_OFF	0
 #define DRM_MODE_DITHERING_ON	1
@@ -107,13 +123,73 @@
 #define DRM_MODE_DIRTY_ON       1
 #define DRM_MODE_DIRTY_ANNOTATE 2
 
+/* Link Status options */
+#define DRM_MODE_LINK_STATUS_GOOD	0
+#define DRM_MODE_LINK_STATUS_BAD	1
+
+/*
+ * DRM_MODE_ROTATE_<degrees>
+ *
+ * Signals that a drm plane is been rotated <degrees> degrees in counter
+ * clockwise direction.
+ *
+ * This define is provided as a convenience, looking up the property id
+ * using the name->prop id lookup is the preferred method.
+ */
+#define DRM_MODE_ROTATE_0       (1<<0)
+#define DRM_MODE_ROTATE_90      (1<<1)
+#define DRM_MODE_ROTATE_180     (1<<2)
+#define DRM_MODE_ROTATE_270     (1<<3)
+
+/*
+ * DRM_MODE_ROTATE_MASK
+ *
+ * Bitmask used to look for drm plane rotations.
+ */
+#define DRM_MODE_ROTATE_MASK (\
+		DRM_MODE_ROTATE_0  | \
+		DRM_MODE_ROTATE_90  | \
+		DRM_MODE_ROTATE_180 | \
+		DRM_MODE_ROTATE_270)
+
+/*
+ * DRM_MODE_REFLECT_<axis>
+ *
+ * Signals that the contents of a drm plane is reflected in the <axis> axis,
+ * in the same way as mirroring.
+ *
+ * This define is provided as a convenience, looking up the property id
+ * using the name->prop id lookup is the preferred method.
+ */
+#define DRM_MODE_REFLECT_X      (1<<4)
+#define DRM_MODE_REFLECT_Y      (1<<5)
+
+/*
+ * DRM_MODE_REFLECT_MASK
+ *
+ * Bitmask used to look for drm plane reflections.
+ */
+#define DRM_MODE_REFLECT_MASK (\
+		DRM_MODE_REFLECT_X | \
+		DRM_MODE_REFLECT_Y)
+
+
+/*
+ * Legacy definitions for old code that doesn't use
+ * the above mask definitions. Don't use in future code.
+ */
 /* rotation property bits */
-#define DRM_ROTATE_0	0
-#define DRM_ROTATE_90	1
-#define DRM_ROTATE_180	2
-#define DRM_ROTATE_270	3
-#define DRM_REFLECT_X	4
-#define DRM_REFLECT_Y	5
+#define DRM_ROTATE_0   0
+#define DRM_ROTATE_90  1
+#define DRM_ROTATE_180 2
+#define DRM_ROTATE_270 3
+#define DRM_REFLECT_X  4
+#define DRM_REFLECT_Y  5
+
+/* Content Protection Flags */
+#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED	0
+#define DRM_MODE_CONTENT_PROTECTION_DESIRED     1
+#define DRM_MODE_CONTENT_PROTECTION_ENABLED     2
 
 struct drm_mode_modeinfo {
 	__u32 clock;
@@ -228,14 +304,16 @@
 
 /* This is for connectors with multiple signal types. */
 /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */
-#define DRM_MODE_SUBCONNECTOR_Automatic	0
-#define DRM_MODE_SUBCONNECTOR_Unknown	0
-#define DRM_MODE_SUBCONNECTOR_DVID	3
-#define DRM_MODE_SUBCONNECTOR_DVIA	4
-#define DRM_MODE_SUBCONNECTOR_Composite	5
-#define DRM_MODE_SUBCONNECTOR_SVIDEO	6
-#define DRM_MODE_SUBCONNECTOR_Component	8
-#define DRM_MODE_SUBCONNECTOR_SCART	9
+enum drm_mode_subconnector {
+	DRM_MODE_SUBCONNECTOR_Automatic = 0,
+	DRM_MODE_SUBCONNECTOR_Unknown = 0,
+	DRM_MODE_SUBCONNECTOR_DVID = 3,
+	DRM_MODE_SUBCONNECTOR_DVIA = 4,
+	DRM_MODE_SUBCONNECTOR_Composite = 5,
+	DRM_MODE_SUBCONNECTOR_SVIDEO = 6,
+	DRM_MODE_SUBCONNECTOR_Component = 8,
+	DRM_MODE_SUBCONNECTOR_SCART = 9,
+};
 
 #define DRM_MODE_CONNECTOR_Unknown	0
 #define DRM_MODE_CONNECTOR_VGA		1
@@ -280,7 +358,7 @@
 	__u32 pad;
 };
 
-#define DRM_MODE_PROP_PENDING	(1<<0)
+#define DRM_MODE_PROP_PENDING	(1<<0) /* deprecated, do not use */
 #define DRM_MODE_PROP_RANGE	(1<<1)
 #define DRM_MODE_PROP_IMMUTABLE	(1<<2)
 #define DRM_MODE_PROP_ENUM	(1<<3) /* enumerated type with text strings */
@@ -400,17 +478,20 @@
 	 * offsets[1].  Note that offsets[0] will generally
 	 * be 0 (but this is not required).
 	 *
-	 * To accommodate tiled, compressed, etc formats, a per-plane
+	 * To accommodate tiled, compressed, etc formats, a
 	 * modifier can be specified.  The default value of zero
 	 * indicates "native" format as specified by the fourcc.
-	 * Vendor specific modifier token.  This allows, for example,
-	 * different tiling/swizzling pattern on different planes.
-	 * See discussion above of DRM_FORMAT_MOD_xxx.
+	 * Vendor specific modifier token.  Note that even though
+	 * it looks like we have a modifier per-plane, we in fact
+	 * do not. The modifier for each plane must be identical.
+	 * Thus all combinations of different data layouts for
+	 * multi plane formats must be enumerated as separate
+	 * modifiers.
 	 */
 	__u32 handles[4];
 	__u32 pitches[4]; /* pitch for each plane */
 	__u32 offsets[4]; /* offset of each plane */
-	__u64 modifier[4]; /* ie, tiling, compressed (per plane) */
+	__u64 modifier[4]; /* ie, tiling, compress */
 };
 
 #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
@@ -512,8 +593,11 @@
 };
 
 struct drm_color_ctm {
-	/* Conversion matrix in S31.32 format. */
-	__s64 matrix[9];
+	/*
+	 * Conversion matrix in S31.32 sign-magnitude
+	 * (not two's complement!) format.
+	 */
+	__u64 matrix[9];
 };
 
 struct drm_color_lut {
@@ -637,13 +721,6 @@
 		DRM_MODE_ATOMIC_NONBLOCK |\
 		DRM_MODE_ATOMIC_ALLOW_MODESET)
 
-#define DRM_MODE_ATOMIC_FLAGS (\
-		DRM_MODE_PAGE_FLIP_EVENT |\
-		DRM_MODE_PAGE_FLIP_ASYNC |\
-		DRM_MODE_ATOMIC_TEST_ONLY |\
-		DRM_MODE_ATOMIC_NONBLOCK |\
-		DRM_MODE_ATOMIC_ALLOW_MODESET)
-
 struct drm_mode_atomic {
 	__u32 flags;
 	__u32 count_objs;
@@ -655,6 +732,56 @@
 	__u64 user_data;
 };
 
+struct drm_format_modifier_blob {
+#define FORMAT_BLOB_CURRENT 1
+	/* Version of this blob format */
+	__u32 version;
+
+	/* Flags */
+	__u32 flags;
+
+	/* Number of fourcc formats supported */
+	__u32 count_formats;
+
+	/* Where in this blob the formats exist (in bytes) */
+	__u32 formats_offset;
+
+	/* Number of drm_format_modifiers */
+	__u32 count_modifiers;
+
+	/* Where in this blob the modifiers exist (in bytes) */
+	__u32 modifiers_offset;
+
+	/* __u32 formats[] */
+	/* struct drm_format_modifier modifiers[] */
+};
+
+struct drm_format_modifier {
+	/* Bitmask of formats in get_plane format list this info applies to. The
+	 * offset allows a sliding window of which 64 formats (bits).
+	 *
+	 * Some examples:
+	 * In today's world with < 65 formats, and formats 0, and 2 are
+	 * supported
+	 * 0x0000000000000005
+	 *		  ^-offset = 0, formats = 5
+	 *
+	 * If the number formats grew to 128, and formats 98-102 are
+	 * supported with the modifier:
+	 *
+	 * 0x0000007c00000000 0000000000000000
+	 *		  ^
+	 *		  |__offset = 64, formats = 0x7c00000000
+	 *
+	 */
+	__u64 formats;
+	__u32 offset;
+	__u32 pad;
+
+	/* The modifier that applies to the >get_plane format list bitmask. */
+	__u64 modifier;
+};
+
 /**
  * Create a new 'blob' data property, copying length bytes from data pointer,
  * and returning new blob ID.
@@ -675,6 +802,72 @@
 	__u32 blob_id;
 };
 
+/**
+ * Lease mode resources, creating another drm_master.
+ */
+struct drm_mode_create_lease {
+	/** Pointer to array of object ids (__u32) */
+	__u64 object_ids;
+	/** Number of object ids */
+	__u32 object_count;
+	/** flags for new FD (O_CLOEXEC, etc) */
+	__u32 flags;
+
+	/** Return: unique identifier for lessee. */
+	__u32 lessee_id;
+	/** Return: file descriptor to new drm_master file */
+	__u32 fd;
+};
+
+/**
+ * List lesses from a drm_master
+ */
+struct drm_mode_list_lessees {
+	/** Number of lessees.
+	 * On input, provides length of the array.
+	 * On output, provides total number. No
+	 * more than the input number will be written
+	 * back, so two calls can be used to get
+	 * the size and then the data.
+	 */
+	__u32 count_lessees;
+	__u32 pad;
+
+	/** Pointer to lessees.
+	 * pointer to __u64 array of lessee ids
+	 */
+	__u64 lessees_ptr;
+};
+
+/**
+ * Get leased objects
+ */
+struct drm_mode_get_lease {
+	/** Number of leased objects.
+	 * On input, provides length of the array.
+	 * On output, provides total number. No
+	 * more than the input number will be written
+	 * back, so two calls can be used to get
+	 * the size and then the data.
+	 */
+	__u32 count_objects;
+	__u32 pad;
+
+	/** Pointer to objects.
+	 * pointer to __u32 array of object ids
+	 */
+	__u64 objects_ptr;
+};
+
+/**
+ * Revoke lease
+ */
+struct drm_mode_revoke_lease {
+	/** Unique ID of lessee
+	 */
+	__u32 lessee_id;
+};
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/drm/drm_sarea.h b/include/drm/drm_sarea.h
index 502934e..93025be 100644
--- a/include/drm/drm_sarea.h
+++ b/include/drm/drm_sarea.h
@@ -34,6 +34,10 @@
 
 #include "drm.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* SAREA area needs to be at least a page */
 #if defined(__alpha__)
 #define SAREA_MAX                       0x2000U
@@ -81,4 +85,8 @@
 typedef struct drm_sarea_frame drm_sarea_frame_t;
 typedef struct drm_sarea drm_sarea_t;
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif				/* _DRM_SAREA_H_ */
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 5ebe046..16e452a 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -86,6 +86,62 @@
 	I915_MOCS_CACHED,
 };
 
+/*
+ * Different engines serve different roles, and there may be more than one
+ * engine serving each role. enum drm_i915_gem_engine_class provides a
+ * classification of the role of the engine, which may be used when requesting
+ * operations to be performed on a certain subset of engines, or for providing
+ * information about that group.
+ */
+enum drm_i915_gem_engine_class {
+	I915_ENGINE_CLASS_RENDER	= 0,
+	I915_ENGINE_CLASS_COPY		= 1,
+	I915_ENGINE_CLASS_VIDEO		= 2,
+	I915_ENGINE_CLASS_VIDEO_ENHANCE	= 3,
+
+	I915_ENGINE_CLASS_INVALID	= -1
+};
+
+/**
+ * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
+ *
+ */
+
+enum drm_i915_pmu_engine_sample {
+	I915_SAMPLE_BUSY = 0,
+	I915_SAMPLE_WAIT = 1,
+	I915_SAMPLE_SEMA = 2
+};
+
+#define I915_PMU_SAMPLE_BITS (4)
+#define I915_PMU_SAMPLE_MASK (0xf)
+#define I915_PMU_SAMPLE_INSTANCE_BITS (8)
+#define I915_PMU_CLASS_SHIFT \
+	(I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS)
+
+#define __I915_PMU_ENGINE(class, instance, sample) \
+	((class) << I915_PMU_CLASS_SHIFT | \
+	(instance) << I915_PMU_SAMPLE_BITS | \
+	(sample))
+
+#define I915_PMU_ENGINE_BUSY(class, instance) \
+	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY)
+
+#define I915_PMU_ENGINE_WAIT(class, instance) \
+	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT)
+
+#define I915_PMU_ENGINE_SEMA(class, instance) \
+	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)
+
+#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))
+
+#define I915_PMU_ACTUAL_FREQUENCY	__I915_PMU_OTHER(0)
+#define I915_PMU_REQUESTED_FREQUENCY	__I915_PMU_OTHER(1)
+#define I915_PMU_INTERRUPTS		__I915_PMU_OTHER(2)
+#define I915_PMU_RC6_RESIDENCY		__I915_PMU_OTHER(3)
+
+#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY
+
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
 #define I915_NR_TEX_REGIONS 255	/* table size 2k - maximum due to use
@@ -260,6 +316,9 @@
 #define DRM_I915_GEM_CONTEXT_GETPARAM	0x34
 #define DRM_I915_GEM_CONTEXT_SETPARAM	0x35
 #define DRM_I915_PERF_OPEN		0x36
+#define DRM_I915_PERF_ADD_CONFIG	0x37
+#define DRM_I915_PERF_REMOVE_CONFIG	0x38
+#define DRM_I915_QUERY			0x39
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -315,6 +374,9 @@
 #define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_PERF_OPEN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
+#define DRM_IOCTL_I915_PERF_ADD_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
+#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
+#define DRM_IOCTL_I915_QUERY			DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -393,10 +455,20 @@
 #define I915_PARAM_MIN_EU_IN_POOL	 39
 #define I915_PARAM_MMAP_GTT_VERSION	 40
 
-/* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
  * priorities and the driver will attempt to execute batches in priority order.
+ * The param returns a capability bitmask, nonzero implies that the scheduler
+ * is enabled, with different features present according to the mask.
+ *
+ * The initial priority for each batch is supplied by the context and is
+ * controlled via I915_CONTEXT_PARAM_PRIORITY.
  */
 #define I915_PARAM_HAS_SCHEDULER	 41
+#define   I915_SCHEDULER_CAP_ENABLED	(1ul << 0)
+#define   I915_SCHEDULER_CAP_PRIORITY	(1ul << 1)
+#define   I915_SCHEDULER_CAP_PREEMPTION	(1ul << 2)
+
 #define I915_PARAM_HUC_STATUS		 42
 
 /* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of
@@ -412,6 +484,51 @@
  */
 #define I915_PARAM_HAS_EXEC_FENCE	 44
 
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture
+ * user specified bufffers for post-mortem debugging of GPU hangs. See
+ * EXEC_OBJECT_CAPTURE.
+ */
+#define I915_PARAM_HAS_EXEC_CAPTURE	 45
+
+#define I915_PARAM_SLICE_MASK		 46
+
+/* Assuming it's uniform for each slice, this queries the mask of subslices
+ * per-slice for this system.
+ */
+#define I915_PARAM_SUBSLICE_MASK	 47
+
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer
+ * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST.
+ */
+#define I915_PARAM_HAS_EXEC_BATCH_FIRST	 48
+
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
+ * drm_i915_gem_exec_fence structures.  See I915_EXEC_FENCE_ARRAY.
+ */
+#define I915_PARAM_HAS_EXEC_FENCE_ARRAY  49
+
+/*
+ * Query whether every context (both per-file default and user created) is
+ * isolated (insofar as HW supports). If this parameter is not true, then
+ * freshly created contexts may inherit values from an existing context,
+ * rather than default HW values. If true, it also ensures (insofar as HW
+ * supports) that all state set by this context will not leak to any other
+ * context.
+ *
+ * As not every engine across every gen support contexts, the returned
+ * value reports the support of context isolation for individual engines by
+ * returning a bitmask of each engine class set to true if that class supports
+ * isolation.
+ */
+#define I915_PARAM_HAS_CONTEXT_ISOLATION 50
+
+/* Frequency of the command streamer timestamps given by the *_TIMESTAMP
+ * registers. This used to be fixed per platform but from CNL onwards, this
+ * might vary depending on the parts.
+ */
+#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
+
 typedef struct drm_i915_getparam {
 	__s32 param;
 	/*
@@ -666,6 +783,8 @@
 #define I915_GEM_DOMAIN_VERTEX		0x00000020
 /** GTT domain - aperture and scanout */
 #define I915_GEM_DOMAIN_GTT		0x00000040
+/** WC domain - uncached access */
+#define I915_GEM_DOMAIN_WC		0x00000080
 /** @} */
 
 struct drm_i915_gem_exec_object {
@@ -773,8 +892,15 @@
  * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously.
  */
 #define EXEC_OBJECT_ASYNC		(1<<6)
+/* Request that the contents of this execobject be copied into the error
+ * state upon a GPU hang involving this batch for post-mortem debugging.
+ * These buffers are recorded in no particular order as "user" in
+ * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see
+ * if the kernel supports this flag.
+ */
+#define EXEC_OBJECT_CAPTURE		(1<<7)
 /* All remaining bits are MBZ and RESERVED FOR FUTURE USE */
-#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_ASYNC<<1)
+#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1)
 	__u64 flags;
 
 	union {
@@ -784,6 +910,18 @@
 	__u64 rsvd2;
 };
 
+struct drm_i915_gem_exec_fence {
+	/**
+	 * User's handle for a drm_syncobj to wait on or signal.
+	 */
+	__u32 handle;
+
+#define I915_EXEC_FENCE_WAIT            (1<<0)
+#define I915_EXEC_FENCE_SIGNAL          (1<<1)
+#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1))
+	__u32 flags;
+};
+
 struct drm_i915_gem_execbuffer2 {
 	/**
 	 * List of gem_exec_object2 structs
@@ -798,7 +936,11 @@
 	__u32 DR1;
 	__u32 DR4;
 	__u32 num_cliprects;
-	/** This is a struct drm_clip_rect *cliprects */
+	/**
+	 * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
+	 * is not set.  If I915_EXEC_FENCE_ARRAY is set, then this is a
+	 * struct drm_i915_gem_exec_fence *fences.
+	 */
 	__u64 cliprects_ptr;
 #define I915_EXEC_RING_MASK              (7<<0)
 #define I915_EXEC_DEFAULT                (0<<0)
@@ -889,7 +1031,24 @@
  */
 #define I915_EXEC_FENCE_OUT		(1<<17)
 
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_OUT<<1))
+/*
+ * Traditionally the execbuf ioctl has only considered the final element in
+ * the execobject[] to be the executable batch. Often though, the client
+ * will known the batch object prior to construction and being able to place
+ * it into the execobject[] array first can simplify the relocation tracking.
+ * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the
+ * execobject[] as the * batch instead (the default is to use the last
+ * element).
+ */
+#define I915_EXEC_BATCH_FIRST		(1<<18)
+
+/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr
+ * define an array of i915_gem_exec_fence structures which specify a set of
+ * dma fences to wait upon or signal.
+ */
+#define I915_EXEC_FENCE_ARRAY   (1<<19)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
 
 #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1201,7 +1360,9 @@
  * active on a given plane.
  */
 
-#define I915_SET_COLORKEY_NONE		(1<<0) /* disable color key matching */
+#define I915_SET_COLORKEY_NONE		(1<<0) /* Deprecated. Instead set
+						* flags==0 to disable colorkeying.
+						*/
 #define I915_SET_COLORKEY_DESTINATION	(1<<1)
 #define I915_SET_COLORKEY_SOURCE	(1<<2)
 struct drm_intel_sprite_colorkey {
@@ -1239,14 +1400,16 @@
 	 * be specified
 	 */
 	__u64 offset;
+#define I915_REG_READ_8B_WA (1ul << 0)
+
 	__u64 val; /* Return value */
 };
 /* Known registers:
  *
  * Render engine timestamp - 0x2358 + 64bit - gen7+
  * - Note this register returns an invalid value if using the default
- *   single instruction 8byte read, in order to workaround that use
- *   offset (0x2538 | 1) instead.
+ *   single instruction 8byte read, in order to workaround that pass
+ *   flag I915_REG_READ_8B_WA in offset field.
  *
  */
 
@@ -1289,17 +1452,26 @@
 #define I915_CONTEXT_PARAM_GTT_SIZE	0x3
 #define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE	0x4
 #define I915_CONTEXT_PARAM_BANNABLE	0x5
+#define I915_CONTEXT_PARAM_PRIORITY	0x6
+#define   I915_CONTEXT_MAX_USER_PRIORITY	1023 /* inclusive */
+#define   I915_CONTEXT_DEFAULT_PRIORITY		0
+#define   I915_CONTEXT_MIN_USER_PRIORITY	-1023 /* inclusive */
 	__u64 value;
 };
 
 enum drm_i915_oa_format {
-	I915_OA_FORMAT_A13 = 1,
-	I915_OA_FORMAT_A29,
-	I915_OA_FORMAT_A13_B8_C8,
-	I915_OA_FORMAT_B4_C8,
-	I915_OA_FORMAT_A45_B8_C8,
-	I915_OA_FORMAT_B4_C8_A16,
-	I915_OA_FORMAT_C4_B8,
+	I915_OA_FORMAT_A13 = 1,	    /* HSW only */
+	I915_OA_FORMAT_A29,	    /* HSW only */
+	I915_OA_FORMAT_A13_B8_C8,   /* HSW only */
+	I915_OA_FORMAT_B4_C8,	    /* HSW only */
+	I915_OA_FORMAT_A45_B8_C8,   /* HSW only */
+	I915_OA_FORMAT_B4_C8_A16,   /* HSW only */
+	I915_OA_FORMAT_C4_B8,	    /* HSW+ */
+
+	/* Gen8+ */
+	I915_OA_FORMAT_A12,
+	I915_OA_FORMAT_A12_B8_C8,
+	I915_OA_FORMAT_A32u40_A4u32_B8_C8,
 
 	I915_OA_FORMAT_MAX	    /* non-ABI */
 };
@@ -1424,6 +1596,127 @@
 	DRM_I915_PERF_RECORD_MAX /* non-ABI */
 };
 
+/**
+ * Structure to upload perf dynamic configuration into the kernel.
+ */
+struct drm_i915_perf_oa_config {
+	/** String formatted like "%08x-%04x-%04x-%04x-%012x" */
+	char uuid[36];
+
+	__u32 n_mux_regs;
+	__u32 n_boolean_regs;
+	__u32 n_flex_regs;
+
+	/*
+	 * These fields are pointers to tuples of u32 values (register address,
+	 * value). For example the expected length of the buffer pointed by
+	 * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs).
+	 */
+	__u64 mux_regs_ptr;
+	__u64 boolean_regs_ptr;
+	__u64 flex_regs_ptr;
+};
+
+struct drm_i915_query_item {
+	__u64 query_id;
+#define DRM_I915_QUERY_TOPOLOGY_INFO    1
+
+	/*
+	 * When set to zero by userspace, this is filled with the size of the
+	 * data to be written at the data_ptr pointer. The kernel sets this
+	 * value to a negative value to signal an error on a particular query
+	 * item.
+	 */
+	__s32 length;
+
+	/*
+	 * Unused for now. Must be cleared to zero.
+	 */
+	__u32 flags;
+
+	/*
+	 * Data will be written at the location pointed by data_ptr when the
+	 * value of length matches the length of the data to be written by the
+	 * kernel.
+	 */
+	__u64 data_ptr;
+};
+
+struct drm_i915_query {
+	__u32 num_items;
+
+	/*
+	 * Unused for now. Must be cleared to zero.
+	 */
+	__u32 flags;
+
+	/*
+	 * This points to an array of num_items drm_i915_query_item structures.
+	 */
+	__u64 items_ptr;
+};
+
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
+ *
+ * data: contains the 3 pieces of information :
+ *
+ * - the slice mask with one bit per slice telling whether a slice is
+ *   available. The availability of slice X can be queried with the following
+ *   formula :
+ *
+ *           (data[X / 8] >> (X % 8)) & 1
+ *
+ * - the subslice mask for each slice with one bit per subslice telling
+ *   whether a subslice is available. The availability of subslice Y in slice
+ *   X can be queried with the following formula :
+ *
+ *           (data[subslice_offset +
+ *                 X * subslice_stride +
+ *                 Y / 8] >> (Y % 8)) & 1
+ *
+ * - the EU mask for each subslice in each slice with one bit per EU telling
+ *   whether an EU is available. The availability of EU Z in subslice Y in
+ *   slice X can be queried with the following formula :
+ *
+ *           (data[eu_offset +
+ *                 (X * max_subslices + Y) * eu_stride +
+ *                 Z / 8] >> (Z % 8)) & 1
+ */
+struct drm_i915_query_topology_info {
+	/*
+	 * Unused for now. Must be cleared to zero.
+	 */
+	__u16 flags;
+
+	__u16 max_slices;
+	__u16 max_subslices;
+	__u16 max_eus_per_subslice;
+
+	/*
+	 * Offset in data[] at which the subslice masks are stored.
+	 */
+	__u16 subslice_offset;
+
+	/*
+	 * Stride at which each of the subslice masks for each slice are
+	 * stored.
+	 */
+	__u16 subslice_stride;
+
+	/*
+	 * Offset in data[] at which the EU masks are stored.
+	 */
+	__u16 eu_offset;
+
+	/*
+	 * Stride at which each of the EU masks for each subslice are stored.
+	 */
+	__u16 eu_stride;
+
+	__u8 data[];
+};
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h
index b630e8f..7930011 100644
--- a/include/drm/mga_drm.h
+++ b/include/drm/mga_drm.h
@@ -37,6 +37,10 @@
 
 #include "drm.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the Xserver file (mga_sarea.h)
  */
@@ -107,7 +111,7 @@
  */
 #define MGA_NR_SAREA_CLIPRECTS	8
 
-/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+/* 2 heaps (1 for card, 1 for agp), each divided into up to 128
  * regions, subject to a minimum region size of (1<<16) == 64k.
  *
  * Clients may subdivide regions internally, but when sharing between
@@ -248,7 +252,7 @@
 #define DRM_MGA_DMA_BOOTSTRAP  0x0c
 
 #define DRM_IOCTL_MGA_INIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
-#define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
+#define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock)
 #define DRM_IOCTL_MGA_RESET    DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_RESET)
 #define DRM_IOCTL_MGA_SWAP     DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_SWAP)
 #define DRM_IOCTL_MGA_CLEAR    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t)
@@ -416,4 +420,8 @@
 	void *value;
 } drm_mga_getparam_t;
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
index 1372f53..91d2f31 100644
--- a/include/drm/nouveau_drm.h
+++ b/include/drm/nouveau_drm.h
@@ -27,6 +27,12 @@
 
 #define NOUVEAU_DRM_HEADER_PATCHLEVEL 16
 
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* reserved object handles when using deprecated object APIs - these
  * are here so that libdrm can allow interoperability with the new
  * object APIs
@@ -106,6 +112,7 @@
 #define NOUVEAU_GEM_DOMAIN_MAPPABLE  (1 << 3)
 #define NOUVEAU_GEM_DOMAIN_COHERENT  (1 << 4)
 
+#define NOUVEAU_GEM_TILE_COMP        0x00030000 /* nv50-only */
 #define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00
 #define NOUVEAU_GEM_TILE_16BPP       0x00000001
 #define NOUVEAU_GEM_TILE_32BPP       0x00000002
@@ -113,13 +120,13 @@
 #define NOUVEAU_GEM_TILE_NONCONTIG   0x00000008
 
 struct drm_nouveau_gem_info {
-	uint32_t handle;
-	uint32_t domain;
-	uint64_t size;
-	uint64_t offset;
-	uint64_t map_handle;
-	uint32_t tile_mode;
-	uint32_t tile_flags;
+	__u32 handle;
+	__u32 domain;
+	__u64 size;
+	__u64 offset;
+	__u64 map_handle;
+	__u32 tile_mode;
+	__u32 tile_flags;
 };
 
 struct drm_nouveau_gem_set_tiling {
@@ -130,23 +137,23 @@
 
 struct drm_nouveau_gem_new {
 	struct drm_nouveau_gem_info info;
-	uint32_t channel_hint;
-	uint32_t align;
+	__u32 channel_hint;
+	__u32 align;
 };
 
 #define NOUVEAU_GEM_MAX_BUFFERS 1024
 struct drm_nouveau_gem_pushbuf_bo_presumed {
-	uint32_t valid;
-	uint32_t domain;
-	uint64_t offset;
+	__u32 valid;
+	__u32 domain;
+	__u64 offset;
 };
 
 struct drm_nouveau_gem_pushbuf_bo {
-	uint64_t user_priv;
-	uint32_t handle;
-	uint32_t read_domains;
-	uint32_t write_domains;
-	uint32_t valid_domains;
+	__u64 user_priv;
+	__u32 handle;
+	__u32 read_domains;
+	__u32 write_domains;
+	__u32 valid_domains;
 	struct drm_nouveau_gem_pushbuf_bo_presumed presumed;
 };
 
@@ -155,35 +162,35 @@
 #define NOUVEAU_GEM_RELOC_OR   (1 << 2)
 #define NOUVEAU_GEM_MAX_RELOCS 1024
 struct drm_nouveau_gem_pushbuf_reloc {
-	uint32_t reloc_bo_index;
-	uint32_t reloc_bo_offset;
-	uint32_t bo_index;
-	uint32_t flags;
-	uint32_t data;
-	uint32_t vor;
-	uint32_t tor;
+	__u32 reloc_bo_index;
+	__u32 reloc_bo_offset;
+	__u32 bo_index;
+	__u32 flags;
+	__u32 data;
+	__u32 vor;
+	__u32 tor;
 };
 
 #define NOUVEAU_GEM_MAX_PUSH 512
 struct drm_nouveau_gem_pushbuf_push {
-	uint32_t bo_index;
-	uint32_t pad;
-	uint64_t offset;
-	uint64_t length;
+	__u32 bo_index;
+	__u32 pad;
+	__u64 offset;
+	__u64 length;
 };
 
 struct drm_nouveau_gem_pushbuf {
-	uint32_t channel;
-	uint32_t nr_buffers;
-	uint64_t buffers;
-	uint32_t nr_relocs;
-	uint32_t nr_push;
-	uint64_t relocs;
-	uint64_t push;
-	uint32_t suffix0;
-	uint32_t suffix1;
-	uint64_t vram_available;
-	uint64_t gart_available;
+	__u32 channel;
+	__u32 nr_buffers;
+	__u64 buffers;
+	__u32 nr_relocs;
+	__u32 nr_push;
+	__u64 relocs;
+	__u64 push;
+	__u32 suffix0;
+	__u32 suffix1;
+	__u64 vram_available;
+	__u64 gart_available;
 };
 
 #define NOUVEAU_GEM_PUSHBUF_2_FENCE_WAIT                             0x00000001
@@ -205,12 +212,12 @@
 #define NOUVEAU_GEM_CPU_PREP_NOBLOCK                                 0x00000002
 #define NOUVEAU_GEM_CPU_PREP_WRITE                                   0x00000004
 struct drm_nouveau_gem_cpu_prep {
-	uint32_t handle;
-	uint32_t flags;
+	__u32 handle;
+	__u32 flags;
 };
 
 struct drm_nouveau_gem_cpu_fini {
-	uint32_t handle;
+	__u32 handle;
 };
 
 #define NOUVEAU_GEM_AS_SPARSE	0x00000001
@@ -287,4 +294,7 @@
 #define DRM_NOUVEAU_GEM_MAP            0x56
 #define DRM_NOUVEAU_GEM_UNMAP          0x57
 
+#if defined(__cplusplus)
+}
+#endif
 #endif /* __NOUVEAU_DRM_H__ */
diff --git a/include/drm/qxl_drm.h b/include/drm/qxl_drm.h
index 1e331a8..38a0dbd 100644
--- a/include/drm/qxl_drm.h
+++ b/include/drm/qxl_drm.h
@@ -27,10 +27,14 @@
 #include <stddef.h>
 #include "drm.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* Please note that modifications to all structs defined here are
  * subject to backwards-compatibility constraints.
  *
- * Do not use pointers, use uint64_t instead for 32 bit / 64 bit user/kernel
+ * Do not use pointers, use __u64 instead for 32 bit / 64 bit user/kernel
  * compatibility Keep fields aligned to their size
  */
 
@@ -48,14 +52,14 @@
 #define DRM_QXL_ALLOC_SURF  0x06
 
 struct drm_qxl_alloc {
-	uint32_t size;
-	uint32_t handle; /* 0 is an invalid handle */
+	__u32 size;
+	__u32 handle; /* 0 is an invalid handle */
 };
 
 struct drm_qxl_map {
-	uint64_t offset; /* use for mmap system call */
-	uint32_t handle;
-	uint32_t pad;
+	__u64 offset; /* use for mmap system call */
+	__u32 handle;
+	__u32 pad;
 };
 
 /*
@@ -68,59 +72,59 @@
 #define QXL_RELOC_TYPE_SURF 2
 
 struct drm_qxl_reloc {
-	uint64_t src_offset; /* offset into src_handle or src buffer */
-	uint64_t dst_offset; /* offset in dest handle */
-	uint32_t src_handle; /* dest handle to compute address from */
-	uint32_t dst_handle; /* 0 if to command buffer */
-	uint32_t reloc_type;
-	uint32_t pad;
+	__u64 src_offset; /* offset into src_handle or src buffer */
+	__u64 dst_offset; /* offset in dest handle */
+	__u32 src_handle; /* dest handle to compute address from */
+	__u32 dst_handle; /* 0 if to command buffer */
+	__u32 reloc_type;
+	__u32 pad;
 };
 
 struct drm_qxl_command {
-	uint64_t	 command; /* void* */
-	uint64_t	 relocs; /* struct drm_qxl_reloc* */
-	uint32_t		type;
-	uint32_t		command_size;
-	uint32_t		relocs_num;
-	uint32_t                pad;
+	__u64		command; /* void* */
+	__u64		relocs; /* struct drm_qxl_reloc* */
+	__u32		type;
+	__u32		command_size;
+	__u32		relocs_num;
+	__u32                pad;
 };
 
 /* XXX: call it drm_qxl_commands? */
 struct drm_qxl_execbuffer {
-	uint32_t		flags;		/* for future use */
-	uint32_t		commands_num;
-	uint64_t	 commands;	/* struct drm_qxl_command* */
+	__u32		flags;		/* for future use */
+	__u32		commands_num;
+	__u64		commands;	/* struct drm_qxl_command* */
 };
 
 struct drm_qxl_update_area {
-	uint32_t handle;
-	uint32_t top;
-	uint32_t left;
-	uint32_t bottom;
-	uint32_t right;
-	uint32_t pad;
+	__u32 handle;
+	__u32 top;
+	__u32 left;
+	__u32 bottom;
+	__u32 right;
+	__u32 pad;
 };
 
 #define QXL_PARAM_NUM_SURFACES 1 /* rom->n_surfaces */
 #define QXL_PARAM_MAX_RELOCS 2
 struct drm_qxl_getparam {
-	uint64_t param;
-	uint64_t value;
+	__u64 param;
+	__u64 value;
 };
 
 /* these are one bit values */
 struct drm_qxl_clientcap {
-	uint32_t index;
-	uint32_t pad;
+	__u32 index;
+	__u32 pad;
 };
 
 struct drm_qxl_alloc_surf {
-	uint32_t format;
-	uint32_t width;
-	uint32_t height;
-	int32_t stride;
-	uint32_t handle;
-	uint32_t pad;
+	__u32 format;
+	__u32 width;
+	__u32 height;
+	__s32 stride;
+	__u32 handle;
+	__u32 pad;
 };
 
 #define DRM_IOCTL_QXL_ALLOC \
@@ -149,4 +153,8 @@
 	DRM_IOWR(DRM_COMMAND_BASE + DRM_QXL_ALLOC_SURF,\
 		struct drm_qxl_alloc_surf)
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/include/drm/r128_drm.h b/include/drm/r128_drm.h
index ede78ff..bf431a0 100644
--- a/include/drm/r128_drm.h
+++ b/include/drm/r128_drm.h
@@ -33,6 +33,12 @@
 #ifndef __R128_DRM_H__
 #define __R128_DRM_H__
 
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the X server file (r128_sarea.h)
  */
@@ -323,4 +329,8 @@
 	void *value;
 } drm_r128_getparam_t;
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index f09cc04..a1e385d 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -797,9 +797,9 @@
 #define RADEON_GEM_DOMAIN_VRAM		0x4
 
 struct drm_radeon_gem_info {
-	uint64_t	gart_size;
-	uint64_t	vram_size;
-	uint64_t	vram_visible;
+	__u64	gart_size;
+	__u64	vram_size;
+	__u64	vram_visible;
 };
 
 #define RADEON_GEM_NO_BACKING_STORE	(1 << 0)
@@ -811,11 +811,11 @@
 #define RADEON_GEM_NO_CPU_ACCESS	(1 << 4)
 
 struct drm_radeon_gem_create {
-	uint64_t	size;
-	uint64_t	alignment;
-	uint32_t	handle;
-	uint32_t	initial_domain;
-	uint32_t	flags;
+	__u64	size;
+	__u64	alignment;
+	__u32	handle;
+	__u32	initial_domain;
+	__u32	flags;
 };
 
 /*
@@ -829,10 +829,10 @@
 #define RADEON_GEM_USERPTR_REGISTER	(1 << 3)
 
 struct drm_radeon_gem_userptr {
-	uint64_t		addr;
-	uint64_t		size;
-	uint32_t		flags;
-	uint32_t		handle;
+	__u64		addr;
+	__u64		size;
+	__u32		flags;
+	__u32		handle;
 };
 
 #define RADEON_TILING_MACRO				0x1
@@ -855,72 +855,72 @@
 #define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK	0xf
 
 struct drm_radeon_gem_set_tiling {
-	uint32_t	handle;
-	uint32_t	tiling_flags;
-	uint32_t	pitch;
+	__u32	handle;
+	__u32	tiling_flags;
+	__u32	pitch;
 };
 
 struct drm_radeon_gem_get_tiling {
-	uint32_t	handle;
-	uint32_t	tiling_flags;
-	uint32_t	pitch;
+	__u32	handle;
+	__u32	tiling_flags;
+	__u32	pitch;
 };
 
 struct drm_radeon_gem_mmap {
-	uint32_t	handle;
-	uint32_t	pad;
-	uint64_t	offset;
-	uint64_t	size;
-	uint64_t	addr_ptr;
+	__u32	handle;
+	__u32	pad;
+	__u64	offset;
+	__u64	size;
+	__u64	addr_ptr;
 };
 
 struct drm_radeon_gem_set_domain {
-	uint32_t	handle;
-	uint32_t	read_domains;
-	uint32_t	write_domain;
+	__u32	handle;
+	__u32	read_domains;
+	__u32	write_domain;
 };
 
 struct drm_radeon_gem_wait_idle {
-	uint32_t	handle;
-	uint32_t	pad;
+	__u32	handle;
+	__u32	pad;
 };
 
 struct drm_radeon_gem_busy {
-	uint32_t	handle;
-	uint32_t        domain;
+	__u32	handle;
+	__u32        domain;
 };
 
 struct drm_radeon_gem_pread {
 	/** Handle for the object being read. */
-	uint32_t handle;
-	uint32_t pad;
+	__u32 handle;
+	__u32 pad;
 	/** Offset into the object to read from */
-	uint64_t offset;
+	__u64 offset;
 	/** Length of data to read */
-	uint64_t size;
+	__u64 size;
 	/** Pointer to write the data into. */
 	/* void *, but pointers are not 32/64 compatible */
-	uint64_t data_ptr;
+	__u64 data_ptr;
 };
 
 struct drm_radeon_gem_pwrite {
 	/** Handle for the object being written to. */
-	uint32_t handle;
-	uint32_t pad;
+	__u32 handle;
+	__u32 pad;
 	/** Offset into the object to write to */
-	uint64_t offset;
+	__u64 offset;
 	/** Length of data to write */
-	uint64_t size;
+	__u64 size;
 	/** Pointer to read the data from. */
 	/* void *, but pointers are not 32/64 compatible */
-	uint64_t data_ptr;
+	__u64 data_ptr;
 };
 
 /* Sets or returns a value associated with a buffer. */
 struct drm_radeon_gem_op {
-	uint32_t	handle; /* buffer */
-	uint32_t	op;     /* RADEON_GEM_OP_* */
-	uint64_t	value;  /* input or return value */
+	__u32	handle; /* buffer */
+	__u32	op;     /* RADEON_GEM_OP_* */
+	__u64	value;  /* input or return value */
 };
 
 #define RADEON_GEM_OP_GET_INITIAL_DOMAIN	0
@@ -940,11 +940,11 @@
 #define RADEON_VM_PAGE_SNOOPED		(1 << 4)
 
 struct drm_radeon_gem_va {
-	uint32_t		handle;
-	uint32_t		operation;
-	uint32_t		vm_id;
-	uint32_t		flags;
-	uint64_t		offset;
+	__u32		handle;
+	__u32		operation;
+	__u32		vm_id;
+	__u32		flags;
+	__u64		offset;
 };
 
 #define RADEON_CHUNK_ID_RELOCS	0x01
@@ -966,29 +966,29 @@
 /* 0 = normal, + = higher priority, - = lower priority */
 
 struct drm_radeon_cs_chunk {
-	uint32_t		chunk_id;
-	uint32_t		length_dw;
-	uint64_t		chunk_data;
+	__u32		chunk_id;
+	__u32		length_dw;
+	__u64		chunk_data;
 };
 
 /* drm_radeon_cs_reloc.flags */
 #define RADEON_RELOC_PRIO_MASK		(0xf << 0)
 
 struct drm_radeon_cs_reloc {
-	uint32_t		handle;
-	uint32_t		read_domains;
-	uint32_t		write_domain;
-	uint32_t		flags;
+	__u32		handle;
+	__u32		read_domains;
+	__u32		write_domain;
+	__u32		flags;
 };
 
 struct drm_radeon_cs {
-	uint32_t		num_chunks;
-	uint32_t		cs_id;
-	/* this points to uint64_t * which point to cs chunks */
-	uint64_t		chunks;
+	__u32		num_chunks;
+	__u32		cs_id;
+	/* this points to __u64 * which point to cs chunks */
+	__u64		chunks;
 	/* updates to the limits after this CS ioctl */
-	uint64_t		gart_limit;
-	uint64_t		vram_limit;
+	__u64		gart_limit;
+	__u64		vram_limit;
 };
 
 #define RADEON_INFO_DEVICE_ID		0x00
@@ -1047,9 +1047,9 @@
 #define RADEON_INFO_GPU_RESET_COUNTER	0x26
 
 struct drm_radeon_info {
-	uint32_t		request;
-	uint32_t		pad;
-	uint64_t		value;
+	__u32		request;
+	__u32		pad;
+	__u64		value;
 };
 
 /* Those correspond to the tile index to use, this is to explicitly state
diff --git a/include/drm/savage_drm.h b/include/drm/savage_drm.h
index f7a75ef..1a91234 100644
--- a/include/drm/savage_drm.h
+++ b/include/drm/savage_drm.h
@@ -26,10 +26,16 @@
 #ifndef __SAVAGE_DRM_H__
 #define __SAVAGE_DRM_H__
 
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 #ifndef __SAVAGE_SAREA_DEFINES__
 #define __SAVAGE_SAREA_DEFINES__
 
-/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+/* 2 heaps (1 for card, 1 for agp), each divided into up to 128
  * regions, subject to a minimum region size of (1<<16) == 64k.
  *
  * Clients may subdivide regions internally, but when sharing between
@@ -63,10 +69,10 @@
 #define DRM_SAVAGE_BCI_EVENT_EMIT	0x02
 #define DRM_SAVAGE_BCI_EVENT_WAIT	0x03
 
-#define DRM_IOCTL_SAVAGE_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
-#define DRM_IOCTL_SAVAGE_CMDBUF		DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
-#define DRM_IOCTL_SAVAGE_EVENT_EMIT	DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
-#define DRM_IOCTL_SAVAGE_EVENT_WAIT	DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
+#define DRM_IOCTL_SAVAGE_BCI_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
+#define DRM_IOCTL_SAVAGE_BCI_CMDBUF		DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
+#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT	DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
+#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT	DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
 
 #define SAVAGE_DMA_PCI	1
 #define SAVAGE_DMA_AGP	3
@@ -207,4 +213,8 @@
 	} clear1;		/* SAVAGE_CMD_CLEAR data */
 };
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/include/drm/sis_drm.h b/include/drm/sis_drm.h
index 30f7b38..8e51bb9 100644
--- a/include/drm/sis_drm.h
+++ b/include/drm/sis_drm.h
@@ -27,6 +27,12 @@
 #ifndef __SIS_DRM_H__
 #define __SIS_DRM_H__
 
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* SiS specific ioctls */
 #define NOT_USED_0_3
 #define DRM_SIS_FB_ALLOC	0x04
@@ -64,4 +70,8 @@
 	unsigned int offset, size;
 } drm_sis_fb_t;
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif				/* __SIS_DRM_H__ */
diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h
index 1be09c4..f01f7a1 100644
--- a/include/drm/tegra_drm.h
+++ b/include/drm/tegra_drm.h
@@ -1,23 +1,33 @@
 /*
  * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
+ * 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:
  *
- * This program is distributed in the hope 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
  */
 
-#ifndef _UAPI_TEGRA_DRM_H_
-#define _UAPI_TEGRA_DRM_H_
+#ifndef _TEGRA_DRM_H_
+#define _TEGRA_DRM_H_
 
-#include <drm/drm.h>
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
 
 #define DRM_TEGRA_GEM_CREATE_TILED     (1 << 0)
 #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
@@ -229,4 +239,8 @@
 #define DRM_IOCTL_TEGRA_START_KEEPON DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_START_KEEPON, struct drm_tegra_keepon)
 #define DRM_IOCTL_TEGRA_STOP_KEEPON DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_STOP_KEEPON, struct drm_tegra_keepon)
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/include/drm/vc4_drm.h b/include/drm/vc4_drm.h
index 319881d..4117117 100644
--- a/include/drm/vc4_drm.h
+++ b/include/drm/vc4_drm.h
@@ -38,6 +38,13 @@
 #define DRM_VC4_CREATE_SHADER_BO                  0x05
 #define DRM_VC4_GET_HANG_STATE                    0x06
 #define DRM_VC4_GET_PARAM                         0x07
+#define DRM_VC4_SET_TILING                        0x08
+#define DRM_VC4_GET_TILING                        0x09
+#define DRM_VC4_LABEL_BO                          0x0a
+#define DRM_VC4_GEM_MADVISE                       0x0b
+#define DRM_VC4_PERFMON_CREATE                    0x0c
+#define DRM_VC4_PERFMON_DESTROY                   0x0d
+#define DRM_VC4_PERFMON_GET_VALUES                0x0e
 
 #define DRM_IOCTL_VC4_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl)
 #define DRM_IOCTL_VC4_WAIT_SEQNO          DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno)
@@ -47,6 +54,13 @@
 #define DRM_IOCTL_VC4_CREATE_SHADER_BO    DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo)
 #define DRM_IOCTL_VC4_GET_HANG_STATE      DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state)
 #define DRM_IOCTL_VC4_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param)
+#define DRM_IOCTL_VC4_SET_TILING          DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling)
+#define DRM_IOCTL_VC4_GET_TILING          DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling)
+#define DRM_IOCTL_VC4_LABEL_BO            DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo)
+#define DRM_IOCTL_VC4_GEM_MADVISE         DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise)
+#define DRM_IOCTL_VC4_PERFMON_CREATE      DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_CREATE, struct drm_vc4_perfmon_create)
+#define DRM_IOCTL_VC4_PERFMON_DESTROY     DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_DESTROY, struct drm_vc4_perfmon_destroy)
+#define DRM_IOCTL_VC4_PERFMON_GET_VALUES  DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_PERFMON_GET_VALUES, struct drm_vc4_perfmon_get_values)
 
 struct drm_vc4_submit_rcl_surface {
 	__u32 hindex; /* Handle index, or ~0 if not present. */
@@ -149,12 +163,31 @@
 	__u32 pad:24;
 
 #define VC4_SUBMIT_CL_USE_CLEAR_COLOR			(1 << 0)
+/* By default, the kernel gets to choose the order that the tiles are
+ * rendered in.  If this is set, then the tiles will be rendered in a
+ * raster order, with the right-to-left vs left-to-right and
+ * top-to-bottom vs bottom-to-top dictated by
+ * VC4_SUBMIT_CL_RCL_ORDER_INCREASING_*.  This allows overlapping
+ * blits to be implemented using the 3D engine.
+ */
+#define VC4_SUBMIT_CL_FIXED_RCL_ORDER			(1 << 1)
+#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X		(1 << 2)
+#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y		(1 << 3)
 	__u32 flags;
 
 	/* Returned value of the seqno of this render job (for the
 	 * wait ioctl).
 	 */
 	__u64 seqno;
+
+	/* ID of the perfmon to attach to this job. 0 means no perfmon. */
+	__u32 perfmonid;
+
+	/* Unused field to align this struct on 64 bits. Must be set to 0.
+	 * If one ever needs to add an u32 field to this struct, this field
+	 * can be used.
+	 */
+	__u32 pad2;
 };
 
 /**
@@ -288,6 +321,9 @@
 #define DRM_VC4_PARAM_SUPPORTS_BRANCHES		3
 #define DRM_VC4_PARAM_SUPPORTS_ETC1		4
 #define DRM_VC4_PARAM_SUPPORTS_THREADED_FS	5
+#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER	6
+#define DRM_VC4_PARAM_SUPPORTS_MADVISE		7
+#define DRM_VC4_PARAM_SUPPORTS_PERFMON		8
 
 struct drm_vc4_get_param {
 	__u32 param;
@@ -295,6 +331,103 @@
 	__u64 value;
 };
 
+struct drm_vc4_get_tiling {
+	__u32 handle;
+	__u32 flags;
+	__u64 modifier;
+};
+
+struct drm_vc4_set_tiling {
+	__u32 handle;
+	__u32 flags;
+	__u64 modifier;
+};
+
+/**
+ * struct drm_vc4_label_bo - Attach a name to a BO for debug purposes.
+ */
+struct drm_vc4_label_bo {
+	__u32 handle;
+	__u32 len;
+	__u64 name;
+};
+
+/*
+ * States prefixed with '__' are internal states and cannot be passed to the
+ * DRM_IOCTL_VC4_GEM_MADVISE ioctl.
+ */
+#define VC4_MADV_WILLNEED			0
+#define VC4_MADV_DONTNEED			1
+#define __VC4_MADV_PURGED			2
+#define __VC4_MADV_NOTSUPP			3
+
+struct drm_vc4_gem_madvise {
+	__u32 handle;
+	__u32 madv;
+	__u32 retained;
+	__u32 pad;
+};
+
+enum {
+	VC4_PERFCNT_FEP_VALID_PRIMS_NO_RENDER,
+	VC4_PERFCNT_FEP_VALID_PRIMS_RENDER,
+	VC4_PERFCNT_FEP_CLIPPED_QUADS,
+	VC4_PERFCNT_FEP_VALID_QUADS,
+	VC4_PERFCNT_TLB_QUADS_NOT_PASSING_STENCIL,
+	VC4_PERFCNT_TLB_QUADS_NOT_PASSING_Z_AND_STENCIL,
+	VC4_PERFCNT_TLB_QUADS_PASSING_Z_AND_STENCIL,
+	VC4_PERFCNT_TLB_QUADS_ZERO_COVERAGE,
+	VC4_PERFCNT_TLB_QUADS_NON_ZERO_COVERAGE,
+	VC4_PERFCNT_TLB_QUADS_WRITTEN_TO_COLOR_BUF,
+	VC4_PERFCNT_PLB_PRIMS_OUTSIDE_VIEWPORT,
+	VC4_PERFCNT_PLB_PRIMS_NEED_CLIPPING,
+	VC4_PERFCNT_PSE_PRIMS_REVERSED,
+	VC4_PERFCNT_QPU_TOTAL_IDLE_CYCLES,
+	VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_VERTEX_COORD_SHADING,
+	VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_FRAGMENT_SHADING,
+	VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_EXEC_VALID_INST,
+	VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_TMUS,
+	VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_SCOREBOARD,
+	VC4_PERFCNT_QPU_TOTAL_CLK_CYCLES_WAITING_VARYINGS,
+	VC4_PERFCNT_QPU_TOTAL_INST_CACHE_HIT,
+	VC4_PERFCNT_QPU_TOTAL_INST_CACHE_MISS,
+	VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_HIT,
+	VC4_PERFCNT_QPU_TOTAL_UNIFORM_CACHE_MISS,
+	VC4_PERFCNT_TMU_TOTAL_TEXT_QUADS_PROCESSED,
+	VC4_PERFCNT_TMU_TOTAL_TEXT_CACHE_MISS,
+	VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VDW_STALLED,
+	VC4_PERFCNT_VPM_TOTAL_CLK_CYCLES_VCD_STALLED,
+	VC4_PERFCNT_L2C_TOTAL_L2_CACHE_HIT,
+	VC4_PERFCNT_L2C_TOTAL_L2_CACHE_MISS,
+	VC4_PERFCNT_NUM_EVENTS,
+};
+
+#define DRM_VC4_MAX_PERF_COUNTERS	16
+
+struct drm_vc4_perfmon_create {
+	__u32 id;
+	__u32 ncounters;
+	__u8 events[DRM_VC4_MAX_PERF_COUNTERS];
+};
+
+struct drm_vc4_perfmon_destroy {
+	__u32 id;
+};
+
+/*
+ * Returns the values of the performance counters tracked by this
+ * perfmon (as an array of ncounters u64 values).
+ *
+ * No implicit synchronization is performed, so the user has to
+ * guarantee that any jobs using this perfmon have already been
+ * completed  (probably by blocking on the seqno returned by the
+ * last exec that used the perfmon).
+ */
+struct drm_vc4_perfmon_get_values {
+	__u32 id;
+	__u64 values_ptr;
+};
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/drm/via_drm.h b/include/drm/via_drm.h
index 182f879..8b69e81 100644
--- a/include/drm/via_drm.h
+++ b/include/drm/via_drm.h
@@ -26,6 +26,10 @@
 
 #include "drm.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 /* WARNING: These defines must be the same as what the Xserver uses.
  * if you change them, you must change the defines in the Xserver.
  */
@@ -272,4 +276,8 @@
 	drm_via_blitsync_t sync;
 } drm_via_dmablit_t;
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif				/* _VIA_DRM_H_ */
diff --git a/include/drm/virtgpu_drm.h b/include/drm/virtgpu_drm.h
index 91a31ff..9a781f0 100644
--- a/include/drm/virtgpu_drm.h
+++ b/include/drm/virtgpu_drm.h
@@ -63,6 +63,7 @@
 };
 
 #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
+#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */
 
 struct drm_virtgpu_getparam {
 	__u64 param;
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
index 5b68b4d..0bc784f 100644
--- a/include/drm/vmwgfx_drm.h
+++ b/include/drm/vmwgfx_drm.h
@@ -30,6 +30,10 @@
 
 #include "drm.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 #define DRM_VMW_MAX_SURFACE_FACES 6
 #define DRM_VMW_MAX_MIP_LEVELS 24
 
@@ -37,6 +41,7 @@
 #define DRM_VMW_GET_PARAM            0
 #define DRM_VMW_ALLOC_DMABUF         1
 #define DRM_VMW_UNREF_DMABUF         2
+#define DRM_VMW_HANDLE_CLOSE         2
 #define DRM_VMW_CURSOR_BYPASS        3
 /* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/
 #define DRM_VMW_CONTROL_STREAM       4
@@ -292,13 +297,17 @@
  * @version: Allows expanding the execbuf ioctl parameters without breaking
  * backwards compatibility, since user-space will always tell the kernel
  * which version it uses.
- * @flags: Execbuf flags. None currently.
+ * @flags: Execbuf flags.
+ * @imported_fence_fd:  FD for a fence imported from another device
  *
  * Argument to the DRM_VMW_EXECBUF Ioctl.
  */
 
 #define DRM_VMW_EXECBUF_VERSION 2
 
+#define DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD (1 << 0)
+#define DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD (1 << 1)
+
 struct drm_vmw_execbuf_arg {
 	__u64 commands;
 	__u32 command_size;
@@ -307,7 +316,7 @@
 	__u32 version;
 	__u32 flags;
 	__u32 context_handle;
-	__u32 pad64;
+	__s32 imported_fence_fd;
 };
 
 /**
@@ -323,6 +332,7 @@
  * @passed_seqno: The highest seqno number processed by the hardware
  * so far. This can be used to mark user-space fence objects as signaled, and
  * to determine whether a fence seqno might be stale.
+ * @fd: FD associated with the fence, -1 if not exported
  * @error: This member should've been set to -EFAULT on submission.
  * The following actions should be take on completion:
  * error == -EFAULT: Fence communication failed. The host is synchronized.
@@ -340,7 +350,7 @@
 	__u32 mask;
 	__u32 seqno;
 	__u32 passed_seqno;
-	__u32 pad64;
+	__s32 fd;
 	__s32 error;
 };
 
@@ -1087,4 +1097,32 @@
 	enum drm_vmw_extended_context req;
 	struct drm_vmw_context_arg rep;
 };
+
+/*************************************************************************/
+/*
+ * DRM_VMW_HANDLE_CLOSE - Close a user-space handle and release its
+ * underlying resource.
+ *
+ * Note that this ioctl is overlaid on the DRM_VMW_UNREF_DMABUF Ioctl.
+ * The ioctl arguments therefore need to be identical in layout.
+ *
+ */
+
+/**
+ * struct drm_vmw_handle_close_arg
+ *
+ * @handle: Handle to close.
+ *
+ * Argument to the DRM_VMW_HANDLE_CLOSE Ioctl.
+ */
+struct drm_vmw_handle_close_arg {
+	__u32 handle;
+	__u32 pad64;
+};
+
+
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/intel/intel-symbol-check b/intel/intel-symbol-check
index 2aa2d81..4d30a4b 100755
--- a/intel/intel-symbol-check
+++ b/intel/intel-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.sources/LIBDRM_INTEL_H_FILES
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_intel.so} | awk '{print $3}' | while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_intel.so} | awk '{print $3}' | while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
diff --git a/intel/intel_bufmgr.c b/intel/intel_bufmgr.c
index 5bad93f..192de09 100644
--- a/intel/intel_bufmgr.c
+++ b/intel/intel_bufmgr.c
@@ -25,10 +25,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
diff --git a/intel/intel_bufmgr_fake.c b/intel/intel_bufmgr_fake.c
index 641df6a..3b24b81 100644
--- a/intel/intel_bufmgr_fake.c
+++ b/intel/intel_bufmgr_fake.c
@@ -34,10 +34,6 @@
  * the bugs in the old texture manager.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index a665600..5c47a46 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -34,10 +34,6 @@
  *	    Dave Airlie <airlied@linux.ie>
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <xf86drm.h>
 #include <xf86atomic.h>
 #include <fcntl.h>
@@ -66,7 +62,7 @@
 #include "i915_drm.h"
 #include "uthash.h"
 
-#ifdef HAVE_VALGRIND
+#if HAVE_VALGRIND
 #include <valgrind.h>
 #include <memcheck.h>
 #define VG(x) x
@@ -270,20 +266,6 @@
 	bool is_userptr;
 
 	/**
-	 * Boolean of whether this buffer can be placed in the full 48-bit
-	 * address range on gen8+.
-	 *
-	 * By default, buffers will be keep in a 32-bit range, unless this
-	 * flag is explicitly set.
-	 */
-	bool use_48b_address_range;
-
-	/**
-	 * Whether this buffer is softpinned at offset specified by the user
-	 */
-	bool is_softpin;
-
-	/**
 	 * Size in bytes of this buffer and its relocation descendents.
 	 *
 	 * Used to avoid costly tree walking in
@@ -438,7 +420,7 @@
 
 		if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) {
 			DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle,
-			    bo_gem->is_softpin ? "*" : "",
+			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
 			    bo_gem->name);
 			continue;
 		}
@@ -452,7 +434,7 @@
 			    "%d (%s)@0x%08x %08x + 0x%08x\n",
 			    i,
 			    bo_gem->gem_handle,
-			    bo_gem->is_softpin ? "*" : "",
+			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
 			    bo_gem->name,
 			    upper_32_bits(bo_gem->relocs[j].offset),
 			    lower_32_bits(bo_gem->relocs[j].offset),
@@ -471,7 +453,7 @@
 			    "%d *(%s)@0x%08x %08x\n",
 			    i,
 			    bo_gem->gem_handle,
-			    bo_gem->is_softpin ? "*" : "",
+			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
 			    bo_gem->name,
 			    target_gem->gem_handle,
 			    target_gem->name,
@@ -541,14 +523,11 @@
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
 	int index;
-	int flags = 0;
+	unsigned long flags;
 
+	flags = 0;
 	if (need_fence)
 		flags |= EXEC_OBJECT_NEEDS_FENCE;
-	if (bo_gem->use_48b_address_range)
-		flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
-	if (bo_gem->is_softpin)
-		flags |= EXEC_OBJECT_PINNED;
 
 	if (bo_gem->validate_index != -1) {
 		bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags;
@@ -579,7 +558,7 @@
 	bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
 	bufmgr_gem->exec2_objects[index].alignment = bo->align;
 	bufmgr_gem->exec2_objects[index].offset = bo->offset64;
-	bufmgr_gem->exec2_objects[index].flags = flags | bo_gem->kflags;
+	bufmgr_gem->exec2_objects[index].flags = bo_gem->kflags | flags;
 	bufmgr_gem->exec2_objects[index].rsvd1 = 0;
 	bufmgr_gem->exec2_objects[index].rsvd2 = 0;
 	bufmgr_gem->exec_bos[index] = bo;
@@ -676,7 +655,6 @@
 	} else {
 		return false;
 	}
-	return (ret == 0 && busy.busy);
 }
 
 static int
@@ -832,6 +810,10 @@
 		}
 
 		bo_gem->gem_handle = create.handle;
+		HASH_ADD(handle_hh, bufmgr_gem->handle_table,
+			 gem_handle, sizeof(bo_gem->gem_handle),
+			 bo_gem);
+
 		bo_gem->bo.handle = bo_gem->gem_handle;
 		bo_gem->bo.bufmgr = bufmgr;
 		bo_gem->bo.align = alignment;
@@ -844,10 +826,6 @@
 							 tiling_mode,
 							 stride))
 			goto err_free;
-
-		HASH_ADD(handle_hh, bufmgr_gem->handle_table,
-			 gem_handle, sizeof(bo_gem->gem_handle),
-			 bo_gem);
 	}
 
 	bo_gem->name = name;
@@ -857,7 +835,6 @@
 	bo_gem->used_as_reloc_target = false;
 	bo_gem->has_error = false;
 	bo_gem->reusable = true;
-	bo_gem->use_48b_address_range = false;
 
 	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment);
 	pthread_mutex_unlock(&bufmgr_gem->lock);
@@ -1016,7 +993,6 @@
 	bo_gem->used_as_reloc_target = false;
 	bo_gem->has_error = false;
 	bo_gem->reusable = false;
-	bo_gem->use_48b_address_range = false;
 
 	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
 	pthread_mutex_unlock(&bufmgr_gem->lock);
@@ -1164,7 +1140,6 @@
 	bo_gem->bo.handle = open_arg.handle;
 	bo_gem->global_name = handle;
 	bo_gem->reusable = false;
-	bo_gem->use_48b_address_range = false;
 
 	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
 		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
@@ -1411,8 +1386,6 @@
 		bo_gem->name = NULL;
 		bo_gem->validate_index = -1;
 
-		bo_gem->kflags = 0;
-
 		DRMLISTADDTAIL(&bo_gem->head, &bucket->head);
 	} else {
 		drm_intel_gem_bo_free(bo);
@@ -1652,7 +1625,7 @@
 drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
-#ifdef HAVE_VALGRIND
+#if HAVE_VALGRIND
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
 #endif
 	int ret;
@@ -2054,7 +2027,11 @@
 drm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable)
 {
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
-	bo_gem->use_48b_address_range = enable;
+
+	if (enable)
+		bo_gem->kflags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
+	else
+		bo_gem->kflags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
 }
 
 static int
@@ -2071,7 +2048,7 @@
 		return -ENOMEM;
 	}
 
-	if (!target_bo_gem->is_softpin)
+	if (!(target_bo_gem->kflags & EXEC_OBJECT_PINNED))
 		return -EINVAL;
 	if (target_bo_gem == bo_gem)
 		return -EINVAL;
@@ -2103,7 +2080,7 @@
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
 	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo;
 
-	if (target_bo_gem->is_softpin)
+	if (target_bo_gem->kflags & EXEC_OBJECT_PINNED)
 		return drm_intel_gem_bo_add_softpin_target(bo, target_bo);
 	else
 		return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
@@ -2287,7 +2264,7 @@
 			/* If we're seeing softpinned object here it means that the kernel
 			 * has relocated our object... Indicating a programming error
 			 */
-			assert(!bo_gem->is_softpin);
+			assert(!(bo_gem->kflags & EXEC_OBJECT_PINNED));
 			DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
 			    bo_gem->gem_handle, bo_gem->name,
 			    upper_32_bits(bo->offset64),
@@ -2643,9 +2620,10 @@
 {
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
 
-	bo_gem->is_softpin = true;
 	bo->offset64 = offset;
 	bo->offset = offset;
+	bo_gem->kflags |= EXEC_OBJECT_PINNED;
+
 	return 0;
 }
 
@@ -2709,7 +2687,6 @@
 	bo_gem->used_as_reloc_target = false;
 	bo_gem->has_error = false;
 	bo_gem->reusable = false;
-	bo_gem->use_48b_address_range = false;
 
 	memclear(get_tiling);
 	get_tiling.handle = bo_gem->gem_handle;
@@ -3681,6 +3658,8 @@
 		bufmgr_gem->gen = 8;
 	else if (IS_GEN9(bufmgr_gem->pci_device))
 		bufmgr_gem->gen = 9;
+	else if (IS_GEN10(bufmgr_gem->pci_device))
+		bufmgr_gem->gen = 10;
 	else {
 		free(bufmgr_gem);
 		bufmgr_gem = NULL;
diff --git a/intel/intel_chipset.h b/intel/intel_chipset.h
index 41fc0da..01d250e 100644
--- a/intel/intel_chipset.h
+++ b/intel/intel_chipset.h
@@ -202,7 +202,7 @@
 #define PCI_CHIP_KABYLAKE_ULX_GT1	0x590E
 #define PCI_CHIP_KABYLAKE_ULX_GT2	0x591E
 #define PCI_CHIP_KABYLAKE_DT_GT2	0x5912
-#define PCI_CHIP_KABYLAKE_DT_GT1_5	0x5917
+#define PCI_CHIP_KABYLAKE_M_GT2		0x5917
 #define PCI_CHIP_KABYLAKE_DT_GT1	0x5902
 #define PCI_CHIP_KABYLAKE_HALO_GT2	0x591B
 #define PCI_CHIP_KABYLAKE_HALO_GT4	0x593B
@@ -221,6 +221,41 @@
 #define PCI_CHIP_GLK			0x3184
 #define PCI_CHIP_GLK_2X6		0x3185
 
+#define PCI_CHIP_COFFEELAKE_S_GT1_1     0x3E90
+#define PCI_CHIP_COFFEELAKE_S_GT1_2     0x3E93
+#define PCI_CHIP_COFFEELAKE_S_GT1_3     0x3E99
+#define PCI_CHIP_COFFEELAKE_S_GT2_1     0x3E91
+#define PCI_CHIP_COFFEELAKE_S_GT2_2     0x3E92
+#define PCI_CHIP_COFFEELAKE_S_GT2_3     0x3E96
+#define PCI_CHIP_COFFEELAKE_S_GT2_4     0x3E9A
+#define PCI_CHIP_COFFEELAKE_H_GT2_1     0x3E9B
+#define PCI_CHIP_COFFEELAKE_H_GT2_2     0x3E94
+#define PCI_CHIP_COFFEELAKE_U_GT1_1     0x3EA1
+#define PCI_CHIP_COFFEELAKE_U_GT1_2     0x3EA4
+#define PCI_CHIP_COFFEELAKE_U_GT2_1     0x3EA0
+#define PCI_CHIP_COFFEELAKE_U_GT2_2     0x3EA3
+#define PCI_CHIP_COFFEELAKE_U_GT2_3     0x3EA9
+#define PCI_CHIP_COFFEELAKE_U_GT3_1     0x3EA2
+#define PCI_CHIP_COFFEELAKE_U_GT3_2     0x3EA5
+#define PCI_CHIP_COFFEELAKE_U_GT3_3     0x3EA6
+#define PCI_CHIP_COFFEELAKE_U_GT3_4     0x3EA7
+#define PCI_CHIP_COFFEELAKE_U_GT3_5     0x3EA8
+
+#define PCI_CHIP_CANNONLAKE_0		0x5A51
+#define PCI_CHIP_CANNONLAKE_1		0x5A59
+#define PCI_CHIP_CANNONLAKE_2		0x5A41
+#define PCI_CHIP_CANNONLAKE_3		0x5A49
+#define PCI_CHIP_CANNONLAKE_4		0x5A52
+#define PCI_CHIP_CANNONLAKE_5		0x5A5A
+#define PCI_CHIP_CANNONLAKE_6		0x5A42
+#define PCI_CHIP_CANNONLAKE_7		0x5A4A
+#define PCI_CHIP_CANNONLAKE_8		0x5A50
+#define PCI_CHIP_CANNONLAKE_9		0x5A40
+#define PCI_CHIP_CANNONLAKE_10		0x5A54
+#define PCI_CHIP_CANNONLAKE_11		0x5A5C
+#define PCI_CHIP_CANNONLAKE_12		0x5A44
+#define PCI_CHIP_CANNONLAKE_13		0x5A4C
+
 #define IS_MOBILE(devid)	((devid) == PCI_CHIP_I855_GM || \
 				 (devid) == PCI_CHIP_I915_GM || \
 				 (devid) == PCI_CHIP_I945_GM || \
@@ -411,7 +446,6 @@
 
 #define IS_KBL_GT1(devid)	((devid) == PCI_CHIP_KABYLAKE_ULT_GT1_5	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_ULX_GT1_5	|| \
-				 (devid) == PCI_CHIP_KABYLAKE_DT_GT1_5	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_ULT_GT1	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_ULX_GT1	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_DT_GT1	|| \
@@ -423,6 +457,7 @@
 				 (devid) == PCI_CHIP_KABYLAKE_ULT_GT2F	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_ULX_GT2	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_DT_GT2	|| \
+				 (devid) == PCI_CHIP_KABYLAKE_M_GT2	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_HALO_GT2	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_SRV_GT2	|| \
 				 (devid) == PCI_CHIP_KABYLAKE_WKS_GT2)
@@ -452,10 +487,54 @@
 #define IS_GEMINILAKE(devid)	((devid) == PCI_CHIP_GLK || \
 				 (devid) == PCI_CHIP_GLK_2X6)
 
+#define IS_CFL_S(devid)         ((devid) == PCI_CHIP_COFFEELAKE_S_GT1_1 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_S_GT1_2 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_S_GT1_3 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_S_GT2_1 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_S_GT2_2 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_S_GT2_3 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_S_GT2_4)
+
+#define IS_CFL_H(devid)         ((devid) == PCI_CHIP_COFFEELAKE_H_GT2_1 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_H_GT2_2)
+
+#define IS_CFL_U(devid)         ((devid) == PCI_CHIP_COFFEELAKE_U_GT1_1 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT1_2 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT2_1 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT2_2 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT2_3 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT3_1 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT3_2 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT3_3 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT3_4 || \
+                                 (devid) == PCI_CHIP_COFFEELAKE_U_GT3_5)
+
+#define IS_COFFEELAKE(devid)   (IS_CFL_S(devid) || \
+				IS_CFL_H(devid) || \
+				IS_CFL_U(devid))
+
 #define IS_GEN9(devid)		(IS_SKYLAKE(devid)  || \
 				 IS_BROXTON(devid)  || \
 				 IS_KABYLAKE(devid) || \
-				 IS_GEMINILAKE(devid))
+				 IS_GEMINILAKE(devid) || \
+				 IS_COFFEELAKE(devid))
+
+#define IS_CANNONLAKE(devid)	((devid) == PCI_CHIP_CANNONLAKE_0 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_1 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_2 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_3 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_4 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_5 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_6 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_7 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_8 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_9 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_10 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_11 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_12 || \
+				 (devid) == PCI_CHIP_CANNONLAKE_13)
+
+#define IS_GEN10(devid)		(IS_CANNONLAKE(devid))
 
 #define IS_9XX(dev)		(IS_GEN3(dev) || \
 				 IS_GEN4(dev) || \
@@ -463,7 +542,7 @@
 				 IS_GEN6(dev) || \
 				 IS_GEN7(dev) || \
 				 IS_GEN8(dev) || \
-				 IS_GEN9(dev))
-
+				 IS_GEN9(dev) || \
+				 IS_GEN10(dev))
 
 #endif /* _INTEL_CHIPSET_H */
diff --git a/intel/intel_decode.c b/intel/intel_decode.c
index 803d202..bc7b04b 100644
--- a/intel/intel_decode.c
+++ b/intel/intel_decode.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <assert.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -3827,7 +3823,9 @@
 	ctx->devid = devid;
 	ctx->out = stdout;
 
-	if (IS_GEN9(devid))
+	if (IS_GEN10(devid))
+		ctx->gen = 10;
+	else if (IS_GEN9(devid))
 		ctx->gen = 9;
 	else if (IS_GEN8(devid))
 		ctx->gen = 8;
@@ -3899,7 +3897,7 @@
 	int ret;
 	unsigned int index = 0;
 	uint32_t devid;
-	int size = ctx->base_count * 4;
+	int size;
 	void *temp;
 
 	if (!ctx)
@@ -3909,6 +3907,7 @@
 	 * the batchbuffer.  This lets us avoid a bunch of length
 	 * checking in statically sized packets.
 	 */
+	size = ctx->base_count * 4;
 	temp = malloc(size + 4096);
 	memcpy(temp, ctx->base_data, size);
 	memset((char *)temp + size, 0xd0, 4096);
diff --git a/intel/meson.build b/intel/meson.build
new file mode 100644
index 0000000..53c7fce
--- /dev/null
+++ b/intel/meson.build
@@ -0,0 +1,106 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+libdrm_intel = shared_library(
+  'drm_intel',
+  [
+    files(
+      'intel_bufmgr.c', 'intel_bufmgr_fake.c', 'intel_bufmgr_gem.c',
+      'intel_decode.c', 'mm.c',
+    ),
+    config_file,
+  ],
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  dependencies : [dep_pciaccess, dep_pthread_stubs, dep_rt, dep_valgrind, dep_atomic_ops],
+  c_args : warn_c_args,
+  version : '1.0.0',
+  install : true,
+)
+
+ext_libdrm_intel = declare_dependency(
+  link_with : [libdrm, libdrm_intel],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+install_headers(
+  'intel_bufmgr.h', 'intel_aub.h', 'intel_debug.h',
+  subdir : 'libdrm',
+)
+
+pkg.generate(
+  name : 'libdrm_intel',
+  libraries : libdrm_intel,
+  subdirs : ['.', 'libdrm'],
+  version : meson.project_version(),
+  requires : 'libdrm',
+  description : 'Userspace interface to intel kernel DRM services',
+)
+
+test_decode = executable(
+  'test_decode',
+  files('test_decode.c'),
+  include_directories : [inc_root, inc_drm],
+  link_with : [libdrm, libdrm_intel],
+  c_args : warn_c_args,
+)
+
+test(
+  'gen4-3d.batch',
+  prog_bash,
+  args : files('tests/gen4-3d.batch.sh'),
+  workdir : meson.current_build_dir(),
+)
+test(
+  'gen45-3d.batch',
+  prog_bash,
+  args : files('tests/gm45-3d.batch.sh'),
+  workdir : meson.current_build_dir(),
+)
+test(
+  'gen5-3d.batch',
+  prog_bash,
+  args : files('tests/gen5-3d.batch.sh'),
+  workdir : meson.current_build_dir(),
+)
+test(
+  'gen6-3d.batch',
+  prog_bash,
+  args : files('tests/gen6-3d.batch.sh'),
+  workdir : meson.current_build_dir(),
+)
+test(
+  'gen7-3d.batch',
+  prog_bash,
+  args : files('tests/gen7-3d.batch.sh'),
+  workdir : meson.current_build_dir(),
+)
+test(
+  'gen7-2d-copy.batch',
+  prog_bash,
+  args : files('tests/gen7-2d-copy.batch.sh'),
+  workdir : meson.current_build_dir(),
+)
+test(
+  'intel-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('intel-symbol-check'), libdrm_intel]
+)
diff --git a/intel/mm.c b/intel/mm.c
index 954e9dc..79d8719 100644
--- a/intel/mm.c
+++ b/intel/mm.c
@@ -22,10 +22,6 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <assert.h>
 
diff --git a/intel/mm.h b/intel/mm.h
index 8d83743..1b0f84f 100644
--- a/intel/mm.h
+++ b/intel/mm.h
@@ -29,10 +29,6 @@
 #ifndef MM_H
 #define MM_H
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "libdrm_macros.h"
 
 struct mem_block {
diff --git a/intel/test_decode.c b/intel/test_decode.c
index b4eddcd..b9f5b92 100644
--- a/intel/test_decode.c
+++ b/intel/test_decode.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -91,7 +87,7 @@
 {
 	FILE *out = NULL;
 	void *ptr, *ref_ptr, *batch_ptr;
-#ifdef HAVE_OPEN_MEMSTREAM
+#if HAVE_OPEN_MEMSTREAM
 	size_t size;
 #endif
 	size_t ref_size, batch_size;
@@ -109,7 +105,7 @@
 	 * figure out how to output to a file in a safe and sane way
 	 * inside of an automake project's test infrastructure.
 	 */
-#ifdef HAVE_OPEN_MEMSTREAM
+#if HAVE_OPEN_MEMSTREAM
 	out = open_memstream((char **)&ptr, &size);
 #else
 	fprintf(stderr, "platform lacks open_memstream, skipping.\n");
diff --git a/libdrm_macros.h b/libdrm_macros.h
index b88fdce..3134ae9 100644
--- a/libdrm_macros.h
+++ b/libdrm_macros.h
@@ -23,7 +23,7 @@
 #ifndef LIBDRM_LIBDRM_H
 #define LIBDRM_LIBDRM_H
 
-#if defined(HAVE_VISIBILITY)
+#if HAVE_VISIBILITY
 #  define drm_private __attribute__((visibility("hidden")))
 #else
 #  define drm_private
diff --git a/libkms/api.c b/libkms/api.c
index 354d8a2..22dd32d 100644
--- a/libkms/api.c
+++ b/libkms/api.c
@@ -26,10 +26,6 @@
  **************************************************************************/
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/libkms/dumb.c b/libkms/dumb.c
index b95a072..17efc10 100644
--- a/libkms/dumb.c
+++ b/libkms/dumb.c
@@ -26,10 +26,6 @@
  **************************************************************************/
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libkms/exynos.c b/libkms/exynos.c
index 0e97fb5..ef64a66 100644
--- a/libkms/exynos.c
+++ b/libkms/exynos.c
@@ -5,16 +5,26 @@
  *	SooChan Lim <sc1.lim@samsung.com>
  *      Sangjin LEE <lsj119@samsung.com>
  *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * 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.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libkms/intel.c b/libkms/intel.c
index 3d8ca05..859e7a0 100644
--- a/libkms/intel.c
+++ b/libkms/intel.c
@@ -26,10 +26,6 @@
  **************************************************************************/
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libkms/internal.h b/libkms/internal.h
index 905f5b1..8b386db 100644
--- a/libkms/internal.h
+++ b/libkms/internal.h
@@ -29,10 +29,6 @@
 #ifndef INTERNAL_H_
 #define INTERNAL_H_
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "libdrm_macros.h"
 #include "libkms.h"
 
diff --git a/libkms/kms-symbol-check b/libkms/kms-symbol-check
index 658b269..a5c2120 100755
--- a/libkms/kms-symbol-check
+++ b/libkms/kms-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.sources/LIBKMS_H_FILES
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libkms.so} | awk '{print $3}'| while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libkms.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
diff --git a/libkms/linux.c b/libkms/linux.c
index 0b50777..5620505 100644
--- a/libkms/linux.c
+++ b/libkms/linux.c
@@ -29,10 +29,6 @@
  * going from fd to pci id via fstat and udev.
  */
 
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -110,27 +106,27 @@
 	if (ret)
 		return ret;
 
-#ifdef HAVE_INTEL
+#if HAVE_INTEL
 	if (!strcmp(name, "intel"))
 		ret = intel_create(fd, out);
 	else
 #endif
-#ifdef HAVE_VMWGFX
+#if HAVE_VMWGFX
 	if (!strcmp(name, "vmwgfx"))
 		ret = vmwgfx_create(fd, out);
 	else
 #endif
-#ifdef HAVE_NOUVEAU
+#if HAVE_NOUVEAU
 	if (!strcmp(name, "nouveau"))
 		ret = nouveau_create(fd, out);
 	else
 #endif
-#ifdef HAVE_RADEON
+#if HAVE_RADEON
 	if (!strcmp(name, "radeon"))
 		ret = radeon_create(fd, out);
 	else
 #endif
-#ifdef HAVE_EXYNOS
+#if HAVE_EXYNOS
 	if (!strcmp(name, "exynos"))
 		ret = exynos_create(fd, out);
 	else
diff --git a/libkms/meson.build b/libkms/meson.build
new file mode 100644
index 0000000..86d1a4e
--- /dev/null
+++ b/libkms/meson.build
@@ -0,0 +1,75 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+libkms_include = [inc_root, inc_drm]
+files_libkms = files(
+  'linux.c',
+  'dumb.c',
+  'api.c',
+)
+if with_vmwgfx
+  files_libkms += files('vmwgfx.c')
+endif
+if with_intel
+  files_libkms += files('intel.c')
+endif
+if with_nouveau
+  files_libkms += files('nouveau.c')
+endif
+if with_radeon
+  files_libkms += files('radeon.c')
+endif
+if with_exynos
+  files_libkms += files('exynos.c')
+  libkms_include += include_directories('../exynos')
+endif
+
+libkms = shared_library(
+  'kms',
+  [files_libkms, config_file],
+  c_args : warn_c_args,
+  include_directories : libkms_include,
+  link_with : libdrm,
+  version : '1.0.0',
+  install : true,
+)
+
+ext_libkms = declare_dependency(
+  link_with : [libdrm, libkms],
+  include_directories : [libkms_include],
+)
+
+install_headers('libkms.h', subdir : 'libkms')
+
+pkg.generate(
+  name : 'libkms',
+  libraries : libkms,
+  subdirs : ['libkms'],
+  version : '1.0.0',
+  requires_private : 'libdrm',
+  description : 'Library that abstracts away the different mm interfaces for kernel drivers',
+)
+
+test(
+  'kms-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('kms-symbol-check'), libkms]
+)
diff --git a/libkms/nouveau.c b/libkms/nouveau.c
index d10e0fd..7fe23db 100644
--- a/libkms/nouveau.c
+++ b/libkms/nouveau.c
@@ -26,10 +26,6 @@
  **************************************************************************/
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libkms/radeon.c b/libkms/radeon.c
index aaeeaf3..2cb2b11 100644
--- a/libkms/radeon.c
+++ b/libkms/radeon.c
@@ -26,10 +26,6 @@
  **************************************************************************/
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libkms/vmwgfx.c b/libkms/vmwgfx.c
index 6a24fd4..f0e40be 100644
--- a/libkms/vmwgfx.c
+++ b/libkms/vmwgfx.c
@@ -26,10 +26,6 @@
  **************************************************************************/
 
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/man/drm-kms.xml b/man/drm-kms.xml
index ae38dc8..eb04c26 100644
--- a/man/drm-kms.xml
+++ b/man/drm-kms.xml
@@ -309,8 +309,8 @@
   <refsect1>
     <title>Reporting Bugs</title>
     <para>Bugs in this manual should be reported to
-          http://bugs.freedesktop.org under the "Mesa" product, with "Other" or
-          "libdrm" as the component.</para>
+      https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&amp;component=libdrm
+      under the "DRI" product, component "libdrm"</para>
   </refsect1>
 
   <refsect1>
diff --git a/man/drm-memory.xml b/man/drm-memory.xml
index 6b4f075..3aa7cf2 100644
--- a/man/drm-memory.xml
+++ b/man/drm-memory.xml
@@ -410,8 +410,8 @@
   <refsect1>
     <title>Reporting Bugs</title>
     <para>Bugs in this manual should be reported to
-          http://bugs.freedesktop.org under the "Mesa" product, with "Other" or
-          "libdrm" as the component.</para>
+      https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&amp;component=libdrm
+      under the "DRI" product, component "libdrm"</para>
   </refsect1>
 
   <refsect1>
diff --git a/man/drm.xml b/man/drm.xml
index 5a49fe1..1f55966 100644
--- a/man/drm.xml
+++ b/man/drm.xml
@@ -50,7 +50,7 @@
 
     <para>In earlier days, the kernel framework was solely used to provide raw
           hardware access to priviledged user-space processes which implement
-          all the hardware abstraction layers. But more and more tasks where
+          all the hardware abstraction layers. But more and more tasks were
           moved into the kernel. All these interfaces are based on
           <citerefentry><refentrytitle>ioctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
           commands on the DRM character device. The <emphasis>libdrm</emphasis>
@@ -119,8 +119,8 @@
   <refsect1>
     <title>Reporting Bugs</title>
     <para>Bugs in this manual should be reported to
-          http://bugs.freedesktop.org under the "Mesa" product, with "Other" or
-          "libdrm" as the component.</para>
+      https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&amp;component=libdrm
+      under the "DRI" product, component "libdrm"</para>
   </refsect1>
 
   <refsect1>
diff --git a/man/drmAvailable.xml b/man/drmAvailable.xml
index 55bef94..1e5d787 100644
--- a/man/drmAvailable.xml
+++ b/man/drmAvailable.xml
@@ -61,8 +61,8 @@
   <refsect1>
     <title>Reporting Bugs</title>
     <para>Bugs in this function should be reported to
-          http://bugs.freedesktop.org under the "Mesa" product, with "Other" or
-          "libdrm" as the component.</para>
+      https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&amp;component=libdrm
+      under the "DRI" product, component "libdrm"</para>
   </refsect1>
 
   <refsect1>
diff --git a/man/drmHandleEvent.xml b/man/drmHandleEvent.xml
index b1006e5..8330442 100644
--- a/man/drmHandleEvent.xml
+++ b/man/drmHandleEvent.xml
@@ -86,8 +86,8 @@
   <refsect1>
     <title>Reporting Bugs</title>
     <para>Bugs in this function should be reported to
-          http://bugs.freedesktop.org under the "Mesa" product, with "Other" or
-          "libdrm" as the component.</para>
+      https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&amp;component=libdrm
+      under the "DRI" product, component "libdrm"</para>
   </refsect1>
 
   <refsect1>
diff --git a/man/drmModeGetResources.xml b/man/drmModeGetResources.xml
index 2f5e8c2..0ab6a68 100644
--- a/man/drmModeGetResources.xml
+++ b/man/drmModeGetResources.xml
@@ -116,8 +116,8 @@
   <refsect1>
     <title>Reporting Bugs</title>
     <para>Bugs in this function should be reported to
-          http://bugs.freedesktop.org under the "Mesa" product, with "Other" or
-          "libdrm" as the component.</para>
+      https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&amp;component=libdrm
+      under the "DRI" product, component "libdrm"</para>
   </refsect1>
 
   <refsect1>
diff --git a/man/meson.build b/man/meson.build
new file mode 100644
index 0000000..45eaeda
--- /dev/null
+++ b/man/meson.build
@@ -0,0 +1,67 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+xsltproc_args = [
+  '--stringparam', 'man.authors.section.enabled', '0',
+  '--stringparam', 'man.copyright.section.enabled', '0',
+  '--stringparam', 'funcsynopsis.style', 'ansi',
+  '--stringparam', 'man.output.quietly', '1',
+  '--nonet', manpage_style,
+]
+
+xmls = [
+  ['drm', '7'], ['drm-kms', '7'], ['drm-memory', '7'], ['drmAvailable', '3'],
+  ['drmHandleEvent', '3'], ['drmModeGetResources', '3']
+]
+foreach x : xmls
+  m = x[0]
+  s = x[1]
+  custom_target(
+    m,
+    input : files('@0@.xml'.format(m)),
+    output : '@0@.@1@'.format(m, s),
+    command : [prog_xslt, '-o', '@OUTPUT@', xsltproc_args, '@INPUT0@'],
+    install : true,
+    install_dir : join_paths(get_option('mandir'), 'man@0@'.format(s)),
+    build_by_default : true,
+  )
+endforeach
+
+foreach x : ['drm-mm', 'drm-gem', 'drm-ttm']
+  gen = custom_target(
+    'gen-@0@'.format(x),
+    input : 'drm-memory.xml',
+    output : '@0@.xml'.format(x),
+    command : [
+      prog_sed, '-e', 's@^\.so \([a-z_]\+\)\.\([0-9]\)$$@\.so man\2\/\1\.\2@',
+      '@INPUT@',
+    ],
+    capture : true,
+  )
+  custom_target(
+    '@0@.7'.format(x),
+    input : gen,
+    output : '@0@.7'.format(x, '7'),
+    command : [prog_xslt, '-o', '@OUTPUT@', xsltproc_args, '@INPUT@'],
+    install : true,
+    install_dir : join_paths(get_option('mandir'), 'man7'),
+    build_by_default : true,
+  )
+endforeach
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..961ee59
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,382 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+project(
+  'libdrm',
+  ['c'],
+  version : '2.4.91',
+  license : 'MIT',
+  meson_version : '>= 0.43',
+  default_options : ['buildtype=debugoptimized', 'c_std=gnu99'],
+)
+
+pkg = import('pkgconfig')
+
+config = configuration_data()
+
+config.set10('UDEV', get_option('udev'))
+with_freedreno_kgsl = get_option('freedreno-kgsl')
+with_install_tests = get_option('install-test-programs')
+
+if ['freebsd', 'dragonfly', 'netbsd'].contains(host_machine.system())
+  dep_pthread_stubs = dependency('pthread-stubs', version : '>= 0.4')
+else
+  dep_pthread_stubs = []
+endif
+dep_threads = dependency('threads')
+
+cc = meson.get_compiler('c')
+
+# Check for atomics
+intel_atomics = false
+lib_atomics = false
+
+dep_atomic_ops = dependency('atomic_ops', required : false)
+if cc.compiles('''
+    int atomic_add(int *i) { return __sync_add_and_fetch (i, 1); }
+    int atomic_cmpxchg(int *i, int j, int k) { return __sync_val_compare_and_swap (i, j, k); }
+    ''',
+    name : 'Intel Atomics')
+  intel_atomics = true
+  with_atomics = true
+  dep_atomic_ops = []
+elif dep_atomic_ops.found()
+  lib_atomics = true
+  with_atomics = true
+elif cc.has_function('atomic_cas_uint')
+  with_atomics = true
+else
+  with_atomics = false
+endif
+
+config.set10('HAVE_LIBDRM_ATOMIC_PRIMITIVES', intel_atomics)
+config.set10('HAVE_LIB_ATOMIC_OPS', lib_atomics)
+
+with_intel = false
+_intel = get_option('intel')
+if _intel != 'false'
+  if _intel == 'true' and not with_atomics
+    error('libdrm_intel requires atomics.')
+  else
+    with_intel = _intel == 'true' or host_machine.cpu_family().startswith('x86')
+  endif
+endif
+
+with_radeon = false
+_radeon = get_option('radeon')
+if _radeon != 'false'
+  if _radeon == 'true' and not with_atomics
+    error('libdrm_radeon requires atomics.')
+  endif
+  with_radeon = true
+endif
+
+with_amdgpu = false
+_amdgpu = get_option('amdgpu')
+if _amdgpu != 'false'
+  if _amdgpu == 'true' and not with_atomics
+    error('libdrm_amdgpu requires atomics.')
+  endif
+  with_amdgpu = true
+endif
+
+with_nouveau = false
+_nouveau = get_option('nouveau')
+if _nouveau != 'false'
+  if _nouveau == 'true' and not with_atomics
+    error('libdrm_nouveau requires atomics.')
+  endif
+  with_nouveau = true
+endif
+
+with_vmwgfx = false
+_vmwgfx = get_option('vmwgfx')
+if _vmwgfx != 'false'
+  with_vmwgfx = true
+endif
+
+with_omap = false
+_omap = get_option('omap')
+if _omap == 'true'
+  if not with_atomics
+    error('libdrm_omap requires atomics.')
+  endif
+  with_omap = true
+endif
+
+with_freedreno = false
+_freedreno = get_option('freedreno')
+if _freedreno != 'false'
+  if _freedreno == 'true' and not with_atomics
+    error('libdrm_freedreno requires atomics.')
+  else
+    with_freedreno = _freedreno == 'true' or ['arm', 'aarch64'].contains(host_machine.cpu_family())
+  endif
+endif
+
+with_tegra = false
+_tegra = get_option('tegra')
+if _tegra == 'true'
+  if not with_atomics
+    error('libdrm_tegra requires atomics.')
+  endif
+  with_tegra = true
+endif
+
+with_etnaviv = false
+_etnaviv = get_option('etnaviv')
+if _etnaviv == 'true'
+  if not with_atomics
+    error('libdrm_etnaviv requires atomics.')
+  endif
+  with_etnaviv = true
+endif
+
+with_exynos = get_option('exynos') == 'true'
+
+with_vc4 = false
+_vc4 = get_option('vc4')
+if _vc4 != 'false'
+  with_vc4 = _vc4 == 'true' or ['arm', 'aarch64'].contains(host_machine.cpu_family())
+endif
+
+# XXX: Aparently only freebsd and dragonfly bsd actually need this (and
+# gnu/kfreebsd), not openbsd and netbsd
+with_libkms = false
+_libkms = get_option('libkms')
+if _libkms != 'false'
+  with_libkms = _libkms == 'true' or ['linux', 'freebsd', 'dragonfly'].contains(host_machine.system())
+endif
+
+# Among others FreeBSD does not have a separate dl library.
+if not cc.has_function('dlsym')
+  dep_dl = cc.find_library('dl', required : with_nouveau)
+else
+  dep_dl = []
+endif
+# clock_gettime might require -rt, or it might not. find out
+if not cc.has_function('clock_gettime', prefix : '#define _GNU_SOURCE\n#include <time.h>')
+  # XXX: untested
+  dep_rt = cc.find_library('rt')
+else
+  dep_rt = []
+endif
+dep_m = cc.find_library('m', required : false)
+foreach header : ['sys/sysctl.h', 'sys/select.h', 'alloca.h']
+  config.set('HAVE_' + header.underscorify().to_upper(),
+    cc.compiles('#include <@0@>'.format(header), name : '@0@ works'.format(header)))
+endforeach
+if cc.has_header_symbol('sys/sysmacros.h', 'major')
+  config.set10('MAJOR_IN_SYSMACROS', true)
+elif cc.has_header_symbol('sys/mkdev.h', 'major')
+  config.set10('MAJOR_IN_MKDEV', true)
+endif
+config.set10('HAVE_OPEN_MEMSTREAM', cc.has_function('open_memstream'))
+
+warn_c_args = []
+foreach a : ['-Wall', '-Wextra', '-Wsign-compare', '-Werror=undef',
+             '-Werror-implicit-function-declaration', '-Wpointer-arith',
+             '-Wwrite-strings', '-Wstrict-prototypes', '-Wmissing-prototypes',
+             '-Wmissing-declarations', '-Wnested-externs', '-Wpacked',
+             '-Wswitch-enum', '-Wmissing-format-attribute',
+             '-Wstrict-aliasing=2', '-Winit-self', '-Winline', '-Wshadow',
+             '-Wdeclaration-after-statement', '-Wold-style-definition']
+  if cc.has_argument(a)
+    warn_c_args += a
+  endif
+endforeach
+# GCC will never error for -Wno-*, so check for -W* then add -Wno-* to the list
+# of options
+foreach a : ['unused-parameter', 'attributes', 'long-long',
+             'missing-field-initializers']
+  if cc.has_argument('-W@0@'.format(a))
+    warn_c_args += '-Wno-@0@'.format(a)
+  endif
+endforeach
+
+
+dep_pciaccess = dependency('pciaccess', version : '>= 0.10', required : with_intel)
+dep_cunit = dependency('cunit', version : '>= 2.1', required : false)
+_cairo_tests = get_option('cairo-tests')
+if _cairo_tests != 'false'
+  dep_cairo = dependency('cairo', required : _cairo_tests == 'true')
+  with_cairo_tests = dep_cairo.found()
+else
+  dep_cairo = []
+  with_cairo_tests = false
+endif
+_valgrind = get_option('valgrind')
+if _valgrind != 'false'
+  dep_valgrind = dependency('valgrind', required : _valgrind == 'true')
+  with_valgrind = dep_valgrind.found()
+else
+  dep_valgrind = []
+  with_valgrind = false
+endif
+
+with_man_pages = get_option('man-pages')
+prog_xslt = find_program('xsltproc', required : with_man_pages == 'true')
+prog_sed = find_program('sed', required : with_man_pages == 'true')
+manpage_style = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
+if prog_xslt.found()
+  if run_command(prog_xslt, '--nonet', manpage_style).returncode() != 0
+    if with_man_pages == 'true'
+      error('Manpage style sheet cannot be found')
+    endif
+    with_man_pages = 'false'
+  endif
+endif
+with_man_pages = with_man_pages != 'false' and prog_xslt.found() and prog_sed.found()
+
+# Used for tets
+prog_bash = find_program('bash')
+
+config.set10('HAVE_VISIBILITY',
+  cc.compiles('''int foo_hidden(void) __attribute__((visibility(("hidden"))));''',
+              name : 'compiler supports __attribute__(("hidden"))'))
+
+foreach t : [
+             [with_exynos, 'EXYNOS'],
+             [with_freedreno_kgsl, 'FREEDRENO_KGSL'],
+             [with_intel, 'INTEL'],
+             [with_nouveau, 'NOUVEAU'],
+             [with_radeon, 'RADEON'],
+             [with_vc4, 'VC4'],
+             [with_vmwgfx, 'VMWGFX'],
+             [with_cairo_tests, 'CAIRO'],
+             [with_valgrind, 'VALGRIND'],
+            ]
+  config.set10('HAVE_@0@'.format(t[1]), t[0])
+endforeach
+if with_freedreno_kgsl and not with_freedreno
+  error('cannot enable freedreno-kgsl without freedreno support')
+endif
+config.set10('_GNU_SOURCE', true)
+config_file = configure_file(
+  configuration : config,
+  output : 'config.h',
+)
+add_project_arguments('-include', 'config.h', language : 'c')
+
+inc_root = include_directories('.')
+inc_drm = include_directories('include/drm')
+
+libdrm = shared_library(
+  'drm',
+  [files(
+     'xf86drm.c', 'xf86drmHash.c', 'xf86drmRandom.c', 'xf86drmSL.c',
+     'xf86drmMode.c'
+   ),
+   config_file,
+  ],
+  c_args : warn_c_args,
+  dependencies : [dep_valgrind, dep_rt, dep_m],
+  include_directories : inc_drm,
+  version : '2.4.0',
+  install : true,
+)
+
+ext_libdrm = declare_dependency(
+  link_with : libdrm,
+  include_directories : [inc_root, inc_drm],
+)
+
+install_headers('libsync.h', 'xf86drm.h', 'xf86drmMode.h')
+install_headers(
+  'include/drm/drm.h', 'include/drm/drm_fourcc.h', 'include/drm/drm_mode.h',
+  'include/drm/drm_sarea.h', 'include/drm/i915_drm.h',
+  'include/drm/mach64_drm.h', 'include/drm/mga_drm.h',
+  'include/drm/nouveau_drm.h', 'include/drm/qxl_drm.h',
+  'include/drm/r128_drm.h', 'include/drm/radeon_drm.h',
+  'include/drm/amdgpu_drm.h', 'include/drm/savage_drm.h',
+  'include/drm/sis_drm.h', 'include/drm/tegra_drm.h', 'include/drm/vc4_drm.h',
+  'include/drm/via_drm.h', 'include/drm/virtgpu_drm.h',
+  subdir : 'libdrm',
+)
+if with_vmwgfx
+  install_headers('include/drm/vmwgfx_drm.h', subdir : 'libdrm')
+endif
+
+pkg.generate(
+  name : 'libdrm',
+  libraries : libdrm,
+  subdirs : ['.', 'libdrm'],
+  version : meson.project_version(),
+  description : 'Userspace interface to kernel DRM services',
+)
+
+env_test = environment()
+env_test.set('NM', find_program('nm').path())
+
+if with_libkms
+  subdir('libkms')
+endif
+if with_intel
+  subdir('intel')
+endif
+if with_nouveau
+  subdir('nouveau')
+endif
+if with_radeon
+  subdir('radeon')
+endif
+if with_amdgpu
+  subdir('amdgpu')
+endif
+if with_omap
+  subdir('omap')
+endif
+if with_exynos
+  subdir('exynos')
+endif
+if with_freedreno
+  subdir('freedreno')
+endif
+if with_tegra
+  subdir('tegra')
+endif
+if with_vc4
+  subdir('vc4')
+endif
+if with_etnaviv
+  subdir('etnaviv')
+endif
+if with_man_pages
+  subdir('man')
+endif
+subdir('data')
+subdir('tests')
+
+message('')
+message('@0@ will be compiled with:'.format(meson.project_name()))
+message('')
+message('  libkms         @0@'.format(with_libkms))
+message('  Intel API      @0@'.format(with_intel))
+message('  vmwgfx API     @0@'.format(with_vmwgfx))
+message('  Radeon API     @0@'.format(with_radeon))
+message('  AMDGPU API     @0@'.format(with_amdgpu))
+message('  Nouveau API    @0@'.format(with_nouveau))
+message('  OMAP API       @0@'.format(with_omap))
+message('  EXYNOS API     @0@'.format(with_exynos))
+message('  Freedreno API  @0@ (kgsl: @1@)'.format(with_freedreno, with_freedreno_kgsl))
+message('  Tegra API      @0@'.format(with_tegra))
+message('  VC4 API        @0@'.format(with_vc4))
+message('  Etnaviv API    @0@'.format(with_etnaviv))
+message('')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..8af33f1
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,143 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+option(
+  'libkms',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : 'Build libkms mm abstraction library.',
+)
+option(
+  'intel',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for Intel's KMS API.''',
+)
+option(
+  'radeon',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for radeons's KMS API.''',
+)
+option(
+  'amdgpu',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for amdgpu's KMS API.''',
+)
+option(
+  'nouveau',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for nouveau's KMS API.''',
+)
+option(
+  'vmwgfx',
+  type : 'combo',
+  value : 'true',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for vmgfx's KMS API.''',
+)
+option(
+  'omap',
+  type : 'combo',
+  value : 'false',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for OMAP's experimental KMS API.''',
+)
+option(
+  'exynos',
+  type : 'combo',
+  value : 'false',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for EXYNOS's experimental KMS API.''',
+)
+option(
+  'freedreno',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for freedreno's KMS API.''',
+)
+option(
+  'tegra',
+  type : 'combo',
+  value : 'false',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for Tegra's experimental KMS API.''',
+)
+option(
+  'vc4',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for vc4's KMS API.''',
+)
+option(
+  'etnaviv',
+  type : 'combo',
+  value : 'false',
+  choices : ['true', 'false', 'auto'],
+  description : '''Enable support for etnaviv's experimental KMS API.''',
+)
+option(
+  'cairo-tests',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : 'Enable support for Cairo rendering in tests.',
+)
+option(
+  'man-pages',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : 'Enable manpage generation and installation.',
+)
+option(
+  'valgrind',
+  type : 'combo',
+  value : 'auto',
+  choices : ['true', 'false', 'auto'],
+  description : 'Build libdrm with valgrind support.',
+)
+option(
+  'freedreno-kgsl',
+  type : 'boolean',
+  value : false,
+  description : 'Enable support for freedreno to use downstream android kernel API.',
+)
+option(
+  'install-test-programs',
+  type : 'boolean',
+  value : false,
+  description : 'Install test programs.',
+)
+option(
+  'udev',
+  type : 'boolean',
+  value : false,
+  description : 'Enable support for using udev instead of mknod.',
+)
diff --git a/nouveau/abi16.c b/nouveau/abi16.c
index ee38c0c..ba2501e 100644
--- a/nouveau/abi16.c
+++ b/nouveau/abi16.c
@@ -22,10 +22,6 @@
  * Authors: Ben Skeggs
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <stddef.h>
diff --git a/nouveau/bufctx.c b/nouveau/bufctx.c
index 4f76e5d..67b7570 100644
--- a/nouveau/bufctx.c
+++ b/nouveau/bufctx.c
@@ -22,10 +22,6 @@
  * Authors: Ben Skeggs
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
diff --git a/nouveau/meson.build b/nouveau/meson.build
new file mode 100644
index 0000000..51c9a71
--- /dev/null
+++ b/nouveau/meson.build
@@ -0,0 +1,59 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+
+libdrm_nouveau = shared_library(
+  'drm_nouveau',
+  [files( 'nouveau.c', 'pushbuf.c', 'bufctx.c', 'abi16.c'), config_file],
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  dependencies : [dep_threads, dep_atomic_ops],
+  version : '2.0.0',
+  install : true,
+)
+
+ext_libdrm_nouveau = declare_dependency(
+  link_with : [libdrm, libdrm_nouveau],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+install_headers('nouveau.h', subdir : 'libdrm/nouveau')
+install_headers(
+  'nvif/class.h', 'nvif/cl0080.h', 'nvif/cl9097.h', 'nvif/if0002.h',
+  'nvif/if0003.h', 'nvif/ioctl.h', 'nvif/unpack.h',
+  subdir : 'libdrm/nouveau/nvif'
+)
+
+pkg.generate(
+  name : 'libdrm_nouveau',
+  libraries : libdrm_nouveau,
+  subdirs : ['.', 'libdrm', 'libdrm/nouveau'],
+  version : meson.project_version(),
+  requires_private : 'libdrm',
+  description : 'Userspace interface to nouveau kernel DRM services',
+)
+
+test(
+  'nouveau-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('nouveau-symbol-check'), libdrm_nouveau]
+)
diff --git a/nouveau/nouveau-symbol-check b/nouveau/nouveau-symbol-check
index b265cea..b3a2410 100755
--- a/nouveau/nouveau-symbol-check
+++ b/nouveau/nouveau-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.sources/LIBDRM_NOUVEAU_H_FILES
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_nouveau.so} | awk '{print $3}'| while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_nouveau.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
index e113a8f..5559351 100644
--- a/nouveau/nouveau.c
+++ b/nouveau/nouveau.c
@@ -22,10 +22,6 @@
  * Authors: Ben Skeggs
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c
index 035e301..445c966 100644
--- a/nouveau/pushbuf.c
+++ b/nouveau/pushbuf.c
@@ -22,10 +22,6 @@
  * Authors: Ben Skeggs
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
diff --git a/omap/Android.bp b/omap/Android.bp
new file mode 100644
index 0000000..05ca7d2
--- /dev/null
+++ b/omap/Android.bp
@@ -0,0 +1,12 @@
+build = ["Android.sources.bp"]
+
+cc_library_shared {
+    name: "libdrm_omap",
+    defaults: [
+        "libdrm_defaults",
+        "libdrm_omap_sources",
+    ],
+    vendor: true,
+
+    shared_libs: ["libdrm"],
+}
diff --git a/omap/Android.sources.bp b/omap/Android.sources.bp
new file mode 100644
index 0000000..3c7da94
--- /dev/null
+++ b/omap/Android.sources.bp
@@ -0,0 +1,8 @@
+// Autogenerated with Android.sources.bp.mk
+
+cc_defaults {
+    name: "libdrm_omap_sources",
+    srcs: [
+	"omap_drm.c",
+    ],
+}
diff --git a/omap/meson.build b/omap/meson.build
new file mode 100644
index 0000000..e57b8f5
--- /dev/null
+++ b/omap/meson.build
@@ -0,0 +1,54 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+libdrm_omap = shared_library(
+  'drm_omap',
+  [files('omap_drm.c'), config_file],
+  include_directories : [inc_root, inc_drm],
+  c_args : warn_c_args,
+  link_with : libdrm,
+  dependencies : [dep_pthread_stubs, dep_atomic_ops],
+  version : '1.0.0',
+  install : true,
+)
+
+ext_libdrm_omap = declare_dependency(
+  link_with : [libdrm, libdrm_omap],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+install_headers('omap_drmif.h', subdir : 'libdrm')
+install_headers('omap_drm.h', subdir : 'omap')
+
+pkg.generate(
+  name : 'libdrm_omap',
+  libraries : libdrm_omap,
+  subdirs : ['.', 'libdrm', 'omap'],
+  version : '0.6',
+  requires_private : 'libdrm',
+  description : 'Userspace interface to omap kernel DRM services',
+)
+
+test(
+  'omap-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('omap-symbol-check'), libdrm_omap]
+)
diff --git a/omap/omap-symbol-check b/omap/omap-symbol-check
index 759c84b..0fb4a0f 100755
--- a/omap/omap-symbol-check
+++ b/omap/omap-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.am/libdrm_omap*HEADERS
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_omap.so} | awk '{print $3}'| while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_omap.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
diff --git a/omap/omap_drm.c b/omap/omap_drm.c
index 08ba64e..65275ec 100644
--- a/omap/omap_drm.c
+++ b/omap/omap_drm.c
@@ -26,10 +26,6 @@
  *    Rob Clark <rob@ti.com>
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
@@ -418,7 +414,7 @@
 	if (bo->fd < 0) {
 		struct drm_prime_handle req = {
 				.handle = bo->handle,
-				.flags = DRM_CLOEXEC,
+				.flags = DRM_CLOEXEC | DRM_RDWR,
 		};
 		int ret;
 
diff --git a/radeon/meson.build b/radeon/meson.build
new file mode 100644
index 0000000..b08c744
--- /dev/null
+++ b/radeon/meson.build
@@ -0,0 +1,64 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+
+libdrm_radeon = shared_library(
+  'drm_radeon',
+  [
+    files(
+      'radeon_bo_gem.c', 'radeon_cs_gem.c', 'radeon_cs_space.c', 'radeon_bo.c',
+      'radeon_cs.c', 'radeon_surface.c',
+    ),
+    config_file,
+  ],
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  dependencies : [dep_pthread_stubs, dep_atomic_ops],
+  version : '1.0.1',
+  install : true,
+)
+
+ext_libdrm_radeon = declare_dependency(
+  link_with : [libdrm, libdrm_radeon],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+install_headers(
+	'radeon_bo.h', 'radeon_cs.h', 'radeon_surface.h', 'radeon_bo_gem.h',
+	'radeon_cs_gem.h', 'radeon_bo_int.h', 'radeon_cs_int.h', 'r600_pci_ids.h',
+  subdir : 'libdrm'
+)
+
+pkg.generate(
+  name : 'libdrm_radeon',
+  libraries : libdrm_radeon,
+  subdirs : ['.', 'libdrm'],
+  version : meson.project_version(),
+  requires_private : 'libdrm',
+  description : 'Userspace interface to kernel DRM services for radeon',
+)
+
+test(
+  'radeon-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('radeon-symbol-check'), libdrm_radeon]
+)
diff --git a/radeon/radeon-symbol-check b/radeon/radeon-symbol-check
index 0bf2ffc..7d79d90 100755
--- a/radeon/radeon-symbol-check
+++ b/radeon/radeon-symbol-check
@@ -3,7 +3,7 @@
 # The following symbols (past the first five) are taken from the public headers.
 # A list of the latter should be available Makefile.sources/LIBDRM_RADEON_H_FILES
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_radeon.so} | awk '{print $3}'| while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_radeon.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
 __bss_start
 _edata
diff --git a/radeon/radeon_bo.c b/radeon/radeon_bo.c
index 447f928..821807b 100644
--- a/radeon/radeon_bo.c
+++ b/radeon/radeon_bo.c
@@ -29,9 +29,6 @@
  *      Dave Airlie
  *      Jérôme Glisse <glisse@freedesktop.org>
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include <libdrm_macros.h>
 #include <radeon_bo.h>
 #include <radeon_bo_int.h>
diff --git a/radeon/radeon_bo_gem.c b/radeon/radeon_bo_gem.c
index fbd453d..774b26e 100644
--- a/radeon/radeon_bo_gem.c
+++ b/radeon/radeon_bo_gem.c
@@ -29,9 +29,6 @@
  *      Dave Airlie
  *      Jérôme Glisse <glisse@freedesktop.org>
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/radeon/radeon_cs.c b/radeon/radeon_cs.c
index dffb869..eb7859e 100644
--- a/radeon/radeon_cs.c
+++ b/radeon/radeon_cs.c
@@ -1,6 +1,3 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include "libdrm_macros.h"
 #include <stdio.h>
 #include "radeon_cs.h"
diff --git a/radeon/radeon_cs_gem.c b/radeon/radeon_cs_gem.c
index f3dccb6..4d5fc13 100644
--- a/radeon/radeon_cs_gem.c
+++ b/radeon/radeon_cs_gem.c
@@ -29,9 +29,6 @@
  *      Nicolai Haehnle <prefect_@gmx.net>
  *      Jérôme Glisse <glisse@freedesktop.org>
  */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
diff --git a/radeon/radeon_cs_space.c b/radeon/radeon_cs_space.c
index 69287be..8531c34 100644
--- a/radeon/radeon_cs_space.c
+++ b/radeon/radeon_cs_space.c
@@ -25,9 +25,6 @@
  */
 /*
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
index 965be24..3cafcfc 100644
--- a/radeon/radeon_surface.c
+++ b/radeon/radeon_surface.c
@@ -26,9 +26,6 @@
  * Authors:
  *      Jérôme Glisse <jglisse@redhat.com>
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
 #include <stdbool.h>
 #include <assert.h>
 #include <errno.h>
@@ -2503,6 +2500,7 @@
         if (surf->npix_y > 1) {
             return -EINVAL;
         }
+        /* fallthrough */
     case RADEON_SURF_TYPE_2D:
         if (surf->npix_z > 1) {
             return -EINVAL;
diff --git a/tegra/meson.build b/tegra/meson.build
new file mode 100644
index 0000000..1f5c74b
--- /dev/null
+++ b/tegra/meson.build
@@ -0,0 +1,53 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+libdrm_tegra = shared_library(
+  'drm_tegra',
+  [files('tegra.c'), config_file],
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  dependencies : [dep_pthread_stubs, dep_atomic_ops],
+  c_args : warn_c_args,
+  version : '0.0.0',
+  install : true,
+)
+
+ext_libdrm_tegra = declare_dependency(
+  link_with : [libdrm, libdrm_tegra],
+  include_directories : [inc_drm, include_directories('.')],
+)
+
+install_headers('tegra.h', subdir : 'libdrm')
+
+pkg.generate(
+  name : 'libdrm_tegra',
+  libraries : libdrm_tegra,
+  subdirs : ['.', 'libdrm'],
+  version : meson.project_version(),
+  requires_private : 'libdrm',
+  description : 'Userspace interface to Tegra kernel DRM services',
+)
+
+test(
+  'tegra-symbol-check',
+  prog_bash,
+  env : env_test,
+  args : [files('tegra-symbol-check'), libdrm_tegra]
+)
diff --git a/tegra/tegra-symbol-check b/tegra/tegra-symbol-check
index 4020831..509b678 100755
--- a/tegra/tegra-symbol-check
+++ b/tegra/tegra-symbol-check
@@ -1,11 +1,14 @@
 #!/bin/bash
 
-# The following symbols (past the first five) are taken from the public headers.
-# A list of the latter should be available Makefile.sources/LIBDRM_FREEDRENO_H_FILES
+# The following symbols (past the first nine) are taken from tegra.h.
 
-FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_tegra.so} | awk '{print $3}'| while read func; do
+FUNCS=$($NM -D --format=bsd --defined-only ${1-.libs/libdrm_tegra.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
+__bss_end__
+__bss_start__
 __bss_start
+__end__
+_bss_end__
 _edata
 _end
 _fini
diff --git a/tegra/tegra.c b/tegra/tegra.c
index 66f19e9..0c86987 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -22,10 +22,6 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
diff --git a/tests/amdgpu/.editorconfig b/tests/amdgpu/.editorconfig
new file mode 120000
index 0000000..70734e4
--- /dev/null
+++ b/tests/amdgpu/.editorconfig
@@ -0,0 +1 @@
+../../amdgpu/.editorconfig
\ No newline at end of file
diff --git a/tests/amdgpu/Makefile.am b/tests/amdgpu/Makefile.am
index c1c3a32..e79c1bd 100644
--- a/tests/amdgpu/Makefile.am
+++ b/tests/amdgpu/Makefile.am
@@ -1,7 +1,8 @@
 AM_CFLAGS = \
 	-I $(top_srcdir)/include/drm \
 	-I $(top_srcdir)/amdgpu \
-	-I $(top_srcdir)
+	-I $(top_srcdir) \
+	-pthread
 
 LDADD = $(top_builddir)/libdrm.la \
 	$(top_builddir)/amdgpu/libdrm_amdgpu.la \
@@ -23,7 +24,12 @@
 	basic_tests.c \
 	bo_tests.c \
 	cs_tests.c \
-	uvd_messages.h \
+	decode_messages.h \
 	vce_tests.c \
 	vce_ib.h \
-	frame.h
+	frame.h \
+	uvd_enc_tests.c \
+	vcn_tests.c \
+	uve_ib.h \
+	deadlock_tests.c \
+	vm_tests.c
diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c
index 3fd6820..96fcd68 100644
--- a/tests/amdgpu/amdgpu_test.c
+++ b/tests/amdgpu/amdgpu_test.c
@@ -21,10 +21,6 @@
  *
 */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -49,6 +45,17 @@
 #include "CUnit/Basic.h"
 
 #include "amdgpu_test.h"
+#include "amdgpu_internal.h"
+
+/* Test suite names */
+#define BASIC_TESTS_STR "Basic Tests"
+#define BO_TESTS_STR "BO Tests"
+#define CS_TESTS_STR "CS Tests"
+#define VCE_TESTS_STR "VCE Tests"
+#define VCN_TESTS_STR "VCN Tests"
+#define UVD_ENC_TESTS_STR "UVD ENC Tests"
+#define DEADLOCK_TESTS_STR "Deadlock Tests"
+#define VM_TESTS_STR "VM Tests"
 
 /**
  *  Open handles for amdgpu devices
@@ -62,49 +69,150 @@
 /** The table of all known test suites to run */
 static CU_SuiteInfo suites[] = {
 	{
-		.pName = "Basic Tests",
+		.pName = BASIC_TESTS_STR,
 		.pInitFunc = suite_basic_tests_init,
 		.pCleanupFunc = suite_basic_tests_clean,
 		.pTests = basic_tests,
 	},
 	{
-		.pName = "BO Tests",
+		.pName = BO_TESTS_STR,
 		.pInitFunc = suite_bo_tests_init,
 		.pCleanupFunc = suite_bo_tests_clean,
 		.pTests = bo_tests,
 	},
 	{
-		.pName = "CS Tests",
+		.pName = CS_TESTS_STR,
 		.pInitFunc = suite_cs_tests_init,
 		.pCleanupFunc = suite_cs_tests_clean,
 		.pTests = cs_tests,
 	},
 	{
-		.pName = "VCE Tests",
+		.pName = VCE_TESTS_STR,
 		.pInitFunc = suite_vce_tests_init,
 		.pCleanupFunc = suite_vce_tests_clean,
 		.pTests = vce_tests,
 	},
+	{
+		.pName = VCN_TESTS_STR,
+		.pInitFunc = suite_vcn_tests_init,
+		.pCleanupFunc = suite_vcn_tests_clean,
+		.pTests = vcn_tests,
+	},
+	{
+		.pName = UVD_ENC_TESTS_STR,
+		.pInitFunc = suite_uvd_enc_tests_init,
+		.pCleanupFunc = suite_uvd_enc_tests_clean,
+		.pTests = uvd_enc_tests,
+	},
+	{
+		.pName = DEADLOCK_TESTS_STR,
+		.pInitFunc = suite_deadlock_tests_init,
+		.pCleanupFunc = suite_deadlock_tests_clean,
+		.pTests = deadlock_tests,
+	},
+	{
+		.pName = VM_TESTS_STR,
+		.pInitFunc = suite_vm_tests_init,
+		.pCleanupFunc = suite_vm_tests_clean,
+		.pTests = vm_tests,
+	},
+
 	CU_SUITE_INFO_NULL,
 };
 
+typedef CU_BOOL (*active__stat_func)(void);
 
-/** Display information about all  suites and their tests */
+typedef struct Suites_Active_Status {
+	char*             pName;
+	active__stat_func pActive;
+}Suites_Active_Status;
+
+static CU_BOOL always_active()
+{
+	return CU_TRUE;
+}
+
+static Suites_Active_Status suites_active_stat[] = {
+		{
+			.pName = BASIC_TESTS_STR,
+			.pActive = always_active,
+		},
+		{
+			.pName = BO_TESTS_STR,
+			.pActive = always_active,
+		},
+		{
+			.pName = CS_TESTS_STR,
+			.pActive = suite_cs_tests_enable,
+		},
+		{
+			.pName = VCE_TESTS_STR,
+			.pActive = suite_vce_tests_enable,
+		},
+		{
+			.pName = VCN_TESTS_STR,
+			.pActive = suite_vcn_tests_enable,
+		},
+		{
+			.pName = UVD_ENC_TESTS_STR,
+			.pActive = suite_uvd_enc_tests_enable,
+		},
+		{
+			.pName = DEADLOCK_TESTS_STR,
+			.pActive = suite_deadlock_tests_enable,
+		},
+		{
+			.pName = VM_TESTS_STR,
+			.pActive = suite_vm_tests_enable,
+		},
+};
+
+
+/*
+ * Display information about all  suites and their tests
+ *
+ * NOTE: Must be run after registry is initialized and suites registered.
+ */
 static void display_test_suites(void)
 {
 	int iSuite;
 	int iTest;
+	CU_pSuite pSuite = NULL;
+	CU_pTest  pTest  = NULL;
 
 	printf("Suites\n");
 
 	for (iSuite = 0; suites[iSuite].pName != NULL; iSuite++) {
-		printf("Suite id = %d: Name '%s'\n",
-				iSuite + 1, suites[iSuite].pName);
+
+		pSuite = CU_get_suite_by_index((unsigned int) iSuite + 1,
+						      CU_get_registry());
+
+		if (!pSuite) {
+			fprintf(stderr, "Invalid suite id : %d\n", iSuite + 1);
+			continue;
+		}
+
+		printf("Suite id = %d: Name '%s status: %s'\n",
+				iSuite + 1, suites[iSuite].pName,
+				pSuite->fActive ? "ENABLED" : "DISABLED");
+
+
 
 		for (iTest = 0; suites[iSuite].pTests[iTest].pName != NULL;
 			iTest++) {
-			printf("	Test id %d: Name: '%s'\n", iTest + 1,
-					suites[iSuite].pTests[iTest].pName);
+
+			pTest = CU_get_test_by_index((unsigned int) iTest + 1,
+									pSuite);
+
+			if (!pTest) {
+				fprintf(stderr, "Invalid test id : %d\n", iTest + 1);
+				continue;
+			}
+
+			printf("Test id %d: Name: '%s status: %s'\n", iTest + 1,
+					suites[iSuite].pTests[iTest].pName,
+					pSuite->fActive && pTest->fActive ?
+						     "ENABLED" : "DISABLED");
 		}
 	}
 }
@@ -112,7 +220,7 @@
 
 /** Help string for command line parameters */
 static const char usage[] =
-	"Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>]] "
+	"Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>] [-f]] "
 	"[-b <pci_bus_id> [-d <pci_device_id>]]\n"
 	"where:\n"
 	"       l - Display all suites and their tests\n"
@@ -120,9 +228,10 @@
 	"       b - Specify device's PCI bus id to run tests\n"
 	"       d - Specify device's PCI device id to run tests (optional)\n"
 	"       p - Display information of AMDGPU devices in system\n"
+	"       f - Force executing inactive suite or test\n"
 	"       h - Display this help\n";
 /** Specified options strings for getopt */
-static const char options[]   = "hlrps:t:b:d:";
+static const char options[]   = "hlrps:t:b:d:f";
 
 /* Open AMD devices.
  * Return the number of AMD device openned.
@@ -130,7 +239,6 @@
 static int amdgpu_open_devices(int open_render_node)
 {
 	drmDevicePtr devices[MAX_CARDS_SUPPORTED];
-	int ret;
 	int i;
 	int drm_node;
 	int amd_index = 0;
@@ -264,29 +372,71 @@
 /* Find a match AMD device in PCI bus
  * Return the index of the device or -1 if not found
  */
-static int amdgpu_find_device(uint8_t bus, uint8_t dev)
+static int amdgpu_find_device(uint8_t bus, uint16_t dev)
 {
 	int i;
 	drmDevicePtr device;
 
-	for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++)
+	for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) {
 		if (drmGetDevice2(drm_amdgpu[i],
 			DRM_DEVICE_GET_PCI_REVISION,
 			&device) == 0) {
 			if (device->bustype == DRM_BUS_PCI)
-				if (device->businfo.pci->bus == bus &&
-					device->businfo.pci->dev == dev) {
-
+				if ((bus == 0xFF || device->businfo.pci->bus == bus) &&
+					device->deviceinfo.pci->device_id == dev) {
 					drmFreeDevice(&device);
 					return i;
 				}
 
 			drmFreeDevice(&device);
 		}
+	}
 
 	return -1;
 }
 
+static void amdgpu_disable_suites()
+{
+	amdgpu_device_handle device_handle;
+	uint32_t major_version, minor_version, family_id;
+	int i;
+	int size = sizeof(suites_active_stat) / sizeof(suites_active_stat[0]);
+
+	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+				   &minor_version, &device_handle))
+		return;
+
+	family_id = device_handle->info.family_id;
+
+	if (amdgpu_device_deinitialize(device_handle))
+		return;
+
+	/* Set active status for suites based on their policies */
+	for (i = 0; i < size; ++i)
+		if (amdgpu_set_suite_active(suites_active_stat[i].pName,
+				suites_active_stat[i].pActive()))
+			fprintf(stderr, "suite deactivation failed - %s\n", CU_get_error_msg());
+
+	/* Explicitly disable specific tests due to known bugs or preferences */
+	/*
+	* BUG: Compute ring stalls and never recovers when the address is
+	* written after the command already submitted
+	*/
+	if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, "compute ring block test", CU_FALSE))
+		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+	if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE))
+		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+	if (amdgpu_set_test_active(BASIC_TESTS_STR, "bo eviction Test", CU_FALSE))
+		fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+
+	/* This test was ran on GFX8 and GFX9 only */
+	if (family_id < AMDGPU_FAMILY_VI || family_id > AMDGPU_FAMILY_RV)
+		if (amdgpu_set_test_active(BASIC_TESTS_STR, "Sync dependency Test", CU_FALSE))
+			fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg());
+}
+
 /* The main() function for setting up and running the tests.
  * Returns a CUE_SUCCESS on successful running, another
  * CUnit error code on failure.
@@ -303,6 +453,8 @@
 	CU_pSuite pSuite = NULL;
 	CU_pTest  pTest  = NULL;
 	int test_device_index;
+	int display_list = 0;
+	int force_run = 0;
 
 	for (i = 0; i < MAX_CARDS_SUPPORTED; i++)
 		drm_amdgpu[i] = -1;
@@ -313,8 +465,8 @@
 	while ((c = getopt(argc, argv, options)) != -1) {
 		switch (c) {
 		case 'l':
-			display_test_suites();
-			exit(EXIT_SUCCESS);
+			display_list = 1;
+			break;
 		case 's':
 			suite_id = atoi(optarg);
 			break;
@@ -325,7 +477,7 @@
 			pci_bus_id = atoi(optarg);
 			break;
 		case 'd':
-			pci_device_id = atoi(optarg);
+			sscanf(optarg, "%x", &pci_device_id);
 			break;
 		case 'p':
 			display_devices = 1;
@@ -333,6 +485,9 @@
 		case 'r':
 			open_render_node = 1;
 			break;
+		case 'f':
+			force_run = 1;
+			break;
 		case '?':
 		case 'h':
 			fprintf(stderr, usage, argv[0]);
@@ -359,10 +514,10 @@
 		exit(EXIT_SUCCESS);
 	}
 
-	if (pci_bus_id > 0) {
+	if (pci_bus_id > 0 || pci_device_id) {
 		/* A device was specified to run the test */
-		test_device_index = amdgpu_find_device((uint8_t)pci_bus_id,
-							(uint8_t)pci_device_id);
+		test_device_index = amdgpu_find_device(pci_bus_id,
+						       pci_device_id);
 
 		if (test_device_index >= 0) {
 			/* Most tests run on device of drm_amdgpu[0].
@@ -398,17 +553,33 @@
 	/* Run tests using the CUnit Basic interface */
 	CU_basic_set_mode(CU_BRM_VERBOSE);
 
+	/* Disable suites and individual tests based on misc. conditions */
+	amdgpu_disable_suites();
+
+	if (display_list) {
+		display_test_suites();
+		goto end;
+	}
+
 	if (suite_id != -1) {	/* If user specify particular suite? */
 		pSuite = CU_get_suite_by_index((unsigned int) suite_id,
 						CU_get_registry());
 
 		if (pSuite) {
+
+			if (force_run)
+				CU_set_suite_active(pSuite, CU_TRUE);
+
 			if (test_id != -1) {   /* If user specify test id */
 				pTest = CU_get_test_by_index(
 						(unsigned int) test_id,
 						pSuite);
-				if (pTest)
+				if (pTest) {
+					if (force_run)
+						CU_set_test_active(pTest, CU_TRUE);
+
 					CU_basic_run_test(pSuite, pTest);
+				}
 				else {
 					fprintf(stderr, "Invalid test id: %d\n",
 								test_id);
@@ -428,6 +599,7 @@
 	} else
 		CU_basic_run_tests();
 
+end:
 	CU_cleanup_registry();
 	amdgpu_close_devices();
 	return CU_get_error();
diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h
index e30e231..6287573 100644
--- a/tests/amdgpu/amdgpu_test.h
+++ b/tests/amdgpu/amdgpu_test.h
@@ -85,6 +85,11 @@
 int suite_cs_tests_clean();
 
 /**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_cs_tests_enable(void);
+
+/**
  * Tests in cs test suite
  */
 extern CU_TestInfo cs_tests[];
@@ -100,11 +105,96 @@
 int suite_vce_tests_clean();
 
 /**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_vce_tests_enable(void);
+
+/**
  * Tests in vce test suite
  */
 extern CU_TestInfo vce_tests[];
 
 /**
++ * Initialize vcn test suite
++ */
+int suite_vcn_tests_init();
+
+/**
++ * Deinitialize vcn test suite
++ */
+int suite_vcn_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_vcn_tests_enable(void);
+
+/**
++ * Tests in vcn test suite
++ */
+extern CU_TestInfo vcn_tests[];
+
+/**
+ * Initialize uvd enc test suite
+ */
+int suite_uvd_enc_tests_init();
+
+/**
+ * Deinitialize uvd enc test suite
+ */
+int suite_uvd_enc_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_uvd_enc_tests_enable(void);
+
+/**
+ * Tests in uvd enc test suite
+ */
+extern CU_TestInfo uvd_enc_tests[];
+
+/**
+ * Initialize deadlock test suite
+ */
+int suite_deadlock_tests_init();
+
+/**
+ * Deinitialize deadlock test suite
+ */
+int suite_deadlock_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_deadlock_tests_enable(void);
+
+/**
+ * Tests in uvd enc test suite
+ */
+extern CU_TestInfo deadlock_tests[];
+
+/**
+ * Initialize vm test suite
+ */
+int suite_vm_tests_init();
+
+/**
+ * Deinitialize deadlock test suite
+ */
+int suite_vm_tests_clean();
+
+/**
+ * Decide if the suite is enabled by default or not.
+ */
+CU_BOOL suite_vm_tests_enable(void);
+
+/**
+ * Tests in vm test suite
+ */
+extern CU_TestInfo vm_tests[];
+
+/**
  * Helper functions
  */
 static inline amdgpu_bo_handle gpu_mem_alloc(
@@ -162,6 +252,29 @@
 }
 
 static inline int
+amdgpu_bo_alloc_wrap(amdgpu_device_handle dev, unsigned size,
+		     unsigned alignment, unsigned heap, uint64_t flags,
+		     amdgpu_bo_handle *bo)
+{
+	struct amdgpu_bo_alloc_request request = {};
+	amdgpu_bo_handle buf_handle;
+	int r;
+
+	request.alloc_size = size;
+	request.phys_alignment = alignment;
+	request.preferred_heap = heap;
+	request.flags = flags;
+
+	r = amdgpu_bo_alloc(dev, &request, &buf_handle);
+	if (r)
+		return r;
+
+	*bo = buf_handle;
+
+	return 0;
+}
+
+static inline int
 amdgpu_bo_alloc_and_map(amdgpu_device_handle dev, unsigned size,
 			unsigned alignment, unsigned heap, uint64_t flags,
 			amdgpu_bo_handle *bo, void **cpu, uint64_t *mc_address,
@@ -236,4 +349,35 @@
 	return amdgpu_bo_list_create(dev, bo2 ? 2 : 1, resources, NULL, list);
 }
 
+
+static inline CU_ErrorCode amdgpu_set_suite_active(const char *suite_name,
+							  CU_BOOL active)
+{
+	CU_ErrorCode r = CU_set_suite_active(CU_get_suite(suite_name), active);
+
+	if (r != CUE_SUCCESS)
+		fprintf(stderr, "Failed to obtain suite %s\n", suite_name);
+
+	return r;
+}
+
+static inline CU_ErrorCode amdgpu_set_test_active(const char *suite_name,
+				  const char *test_name, CU_BOOL active)
+{
+	CU_ErrorCode r;
+	CU_pSuite pSuite = CU_get_suite(suite_name);
+
+	if (!pSuite) {
+		fprintf(stderr, "Failed to obtain suite %s\n",
+				suite_name);
+		return CUE_NOSUITE;
+	}
+
+	r = CU_set_test_active(CU_get_test(pSuite, test_name), active);
+	if (r != CUE_SUCCESS)
+		fprintf(stderr, "Failed to obtain test %s\n", test_name);
+
+	return r;
+}
+
 #endif  /* #ifdef _AMDGPU_TEST_H_ */
diff --git a/tests/amdgpu/basic_tests.c b/tests/amdgpu/basic_tests.c
index bfda21b..1adbddd 100644
--- a/tests/amdgpu/basic_tests.c
+++ b/tests/amdgpu/basic_tests.c
@@ -21,16 +21,13 @@
  *
 */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #ifdef HAVE_ALLOCA_H
 # include <alloca.h>
 #endif
+#include <sys/wait.h>
 
 #include "CUnit/Basic.h"
 
@@ -40,27 +37,38 @@
 static  amdgpu_device_handle device_handle;
 static  uint32_t  major_version;
 static  uint32_t  minor_version;
+static  uint32_t  family_id;
 
 static void amdgpu_query_info_test(void);
-static void amdgpu_memory_alloc(void);
 static void amdgpu_command_submission_gfx(void);
 static void amdgpu_command_submission_compute(void);
+static void amdgpu_command_submission_multi_fence(void);
 static void amdgpu_command_submission_sdma(void);
 static void amdgpu_userptr_test(void);
 static void amdgpu_semaphore_test(void);
+static void amdgpu_sync_dependency_test(void);
+static void amdgpu_bo_eviction_test(void);
 
 static void amdgpu_command_submission_write_linear_helper(unsigned ip_type);
 static void amdgpu_command_submission_const_fill_helper(unsigned ip_type);
 static void amdgpu_command_submission_copy_linear_helper(unsigned ip_type);
-
+static void amdgpu_test_exec_cs_helper(amdgpu_context_handle context_handle,
+				       unsigned ip_type,
+				       int instance, int pm4_dw, uint32_t *pm4_src,
+				       int res_cnt, amdgpu_bo_handle *resources,
+				       struct amdgpu_cs_ib_info *ib_info,
+				       struct amdgpu_cs_request *ibs_request);
+ 
 CU_TestInfo basic_tests[] = {
 	{ "Query Info Test",  amdgpu_query_info_test },
-	{ "Memory alloc Test",  amdgpu_memory_alloc },
 	{ "Userptr Test",  amdgpu_userptr_test },
+	{ "bo eviction Test",  amdgpu_bo_eviction_test },
 	{ "Command submission Test (GFX)",  amdgpu_command_submission_gfx },
 	{ "Command submission Test (Compute)", amdgpu_command_submission_compute },
+	{ "Command submission Test (Multi-Fence)", amdgpu_command_submission_multi_fence },
 	{ "Command submission Test (SDMA)", amdgpu_command_submission_sdma },
 	{ "SW semaphore Test",  amdgpu_semaphore_test },
+	{ "Sync dependency Test",  amdgpu_sync_dependency_test },
 	CU_TEST_INFO_NULL,
 };
 #define BUFFER_SIZE (8 * 1024)
@@ -197,22 +205,110 @@
 #              define PACKET3_DMA_DATA_CMD_DAIC    (1 << 29)
 #              define PACKET3_DMA_DATA_CMD_RAW_WAIT  (1 << 30)
 
+#define SDMA_PACKET_SI(op, b, t, s, cnt)	((((op) & 0xF) << 28) |	\
+						(((b) & 0x1) << 26) |		\
+						(((t) & 0x1) << 23) |		\
+						(((s) & 0x1) << 22) |		\
+						(((cnt) & 0xFFFFF) << 0))
+#define	SDMA_OPCODE_COPY_SI	3
+#define SDMA_OPCODE_CONSTANT_FILL_SI	13
+#define SDMA_NOP_SI  0xf
+#define GFX_COMPUTE_NOP_SI 0x80000000
+#define	PACKET3_DMA_DATA_SI	0x41
+#              define PACKET3_DMA_DATA_SI_ENGINE(x)     ((x) << 27)
+		/* 0 - ME
+		 * 1 - PFP
+		 */
+#              define PACKET3_DMA_DATA_SI_DST_SEL(x)  ((x) << 20)
+		/* 0 - DST_ADDR using DAS
+		 * 1 - GDS
+		 * 3 - DST_ADDR using L2
+		 */
+#              define PACKET3_DMA_DATA_SI_SRC_SEL(x)  ((x) << 29)
+		/* 0 - SRC_ADDR using SAS
+		 * 1 - GDS
+		 * 2 - DATA
+		 * 3 - SRC_ADDR using L2
+		 */
+#              define PACKET3_DMA_DATA_SI_CP_SYNC     (1 << 31)
+
+
+#define PKT3_CONTEXT_CONTROL                   0x28
+#define     CONTEXT_CONTROL_LOAD_ENABLE(x)     (((unsigned)(x) & 0x1) << 31)
+#define     CONTEXT_CONTROL_LOAD_CE_RAM(x)     (((unsigned)(x) & 0x1) << 28)
+#define     CONTEXT_CONTROL_SHADOW_ENABLE(x)   (((unsigned)(x) & 0x1) << 31)
+
+#define PKT3_CLEAR_STATE                       0x12
+
+#define PKT3_SET_SH_REG                        0x76
+#define		PACKET3_SET_SH_REG_START			0x00002c00
+
+#define	PACKET3_DISPATCH_DIRECT				0x15
+
+
+/* gfx 8 */
+#define mmCOMPUTE_PGM_LO                                                        0x2e0c
+#define mmCOMPUTE_PGM_RSRC1                                                     0x2e12
+#define mmCOMPUTE_TMPRING_SIZE                                                  0x2e18
+#define mmCOMPUTE_USER_DATA_0                                                   0x2e40
+#define mmCOMPUTE_USER_DATA_1                                                   0x2e41
+#define mmCOMPUTE_RESOURCE_LIMITS                                               0x2e15
+#define mmCOMPUTE_NUM_THREAD_X                                                  0x2e07
+
+
+
+#define SWAP_32(num) (((num & 0xff000000) >> 24) | \
+		      ((num & 0x0000ff00) << 8) | \
+		      ((num & 0x00ff0000) >> 8) | \
+		      ((num & 0x000000ff) << 24))
+
+
+/* Shader code
+ * void main()
+{
+
+	float x = some_input;
+		for (unsigned i = 0; i < 1000000; i++)
+  	x = sin(x);
+
+	u[0] = 42u;
+}
+*/
+
+static  uint32_t shader_bin[] = {
+	SWAP_32(0x800082be), SWAP_32(0x02ff08bf), SWAP_32(0x7f969800), SWAP_32(0x040085bf),
+	SWAP_32(0x02810281), SWAP_32(0x02ff08bf), SWAP_32(0x7f969800), SWAP_32(0xfcff84bf),
+	SWAP_32(0xff0083be), SWAP_32(0x00f00000), SWAP_32(0xc10082be), SWAP_32(0xaa02007e),
+	SWAP_32(0x000070e0), SWAP_32(0x00000080), SWAP_32(0x000081bf)
+};
+
+#define CODE_OFFSET 512
+#define DATA_OFFSET 1024
+
+
 int suite_basic_tests_init(void)
 {
+	struct amdgpu_gpu_info gpu_info = {0};
 	int r;
 
 	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
 				   &minor_version, &device_handle);
 
-	if (r == 0)
-		return CUE_SUCCESS;
-	else {
+	if (r) {
 		if ((r == -EACCES) && (errno == EACCES))
 			printf("\n\nError:%s. "
 				"Hint:Try to run this test program as root.",
 				strerror(errno));
 		return CUE_SINIT_FAILED;
 	}
+
+	r = amdgpu_query_gpu_info(device_handle, &gpu_info);
+	if (r)
+		return CUE_SINIT_FAILED;
+
+	family_id = gpu_info.family_id;
+
+	return CUE_SUCCESS;
 }
 
 int suite_basic_tests_clean(void)
@@ -239,53 +335,6 @@
 	CU_ASSERT_EQUAL(r, 0);
 }
 
-static void amdgpu_memory_alloc(void)
-{
-	amdgpu_bo_handle bo;
-	amdgpu_va_handle va_handle;
-	uint64_t bo_mc;
-	int r;
-
-	/* Test visible VRAM */
-	bo = gpu_mem_alloc(device_handle,
-			4096, 4096,
-			AMDGPU_GEM_DOMAIN_VRAM,
-			AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-			&bo_mc, &va_handle);
-
-	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
-	CU_ASSERT_EQUAL(r, 0);
-
-	/* Test invisible VRAM */
-	bo = gpu_mem_alloc(device_handle,
-			4096, 4096,
-			AMDGPU_GEM_DOMAIN_VRAM,
-			AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
-			&bo_mc, &va_handle);
-
-	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
-	CU_ASSERT_EQUAL(r, 0);
-
-	/* Test GART Cacheable */
-	bo = gpu_mem_alloc(device_handle,
-			4096, 4096,
-			AMDGPU_GEM_DOMAIN_GTT,
-			0, &bo_mc, &va_handle);
-
-	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
-	CU_ASSERT_EQUAL(r, 0);
-
-	/* Test GART USWC */
-	bo = gpu_mem_alloc(device_handle,
-			4096, 4096,
-			AMDGPU_GEM_DOMAIN_GTT,
-			AMDGPU_GEM_CREATE_CPU_GTT_USWC,
-			&bo_mc, &va_handle);
-
-	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
-	CU_ASSERT_EQUAL(r, 0);
-}
-
 static void amdgpu_command_submission_gfx_separate_ibs(void)
 {
 	amdgpu_context_handle context_handle;
@@ -299,7 +348,7 @@
 	uint32_t expired;
 	amdgpu_bo_list_handle bo_list;
 	amdgpu_va_handle va_handle, va_handle_ce;
-	int r;
+	int r, i = 0;
 
 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
 	CU_ASSERT_EQUAL(r, 0);
@@ -324,12 +373,14 @@
 
 	/* IT_SET_CE_DE_COUNTERS */
 	ptr = ib_result_ce_cpu;
-	ptr[0] = 0xc0008900;
-	ptr[1] = 0;
-	ptr[2] = 0xc0008400;
-	ptr[3] = 1;
+	if (family_id != AMDGPU_FAMILY_SI) {
+		ptr[i++] = 0xc0008900;
+		ptr[i++] = 0;
+	}
+	ptr[i++] = 0xc0008400;
+	ptr[i++] = 1;
 	ib_info[0].ib_mc_address = ib_result_ce_mc_address;
-	ib_info[0].size = 4;
+	ib_info[0].size = i;
 	ib_info[0].flags = AMDGPU_IB_FLAG_CE;
 
 	/* IT_WAIT_ON_CE_COUNTER */
@@ -388,7 +439,7 @@
 	uint32_t expired;
 	amdgpu_bo_list_handle bo_list;
 	amdgpu_va_handle va_handle;
-	int r;
+	int r, i = 0;
 
 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
 	CU_ASSERT_EQUAL(r, 0);
@@ -407,12 +458,14 @@
 
 	/* IT_SET_CE_DE_COUNTERS */
 	ptr = ib_result_cpu;
-	ptr[0] = 0xc0008900;
-	ptr[1] = 0;
-	ptr[2] = 0xc0008400;
-	ptr[3] = 1;
+	if (family_id != AMDGPU_FAMILY_SI) {
+		ptr[i++] = 0xc0008900;
+		ptr[i++] = 0;
+	}
+	ptr[i++] = 0xc0008400;
+	ptr[i++] = 1;
 	ib_info[0].ib_mc_address = ib_result_mc_address;
-	ib_info[0].size = 4;
+	ib_info[0].size = i;
 	ib_info[0].flags = AMDGPU_IB_FLAG_CE;
 
 	ptr = (uint32_t *)ib_result_cpu + 4;
@@ -467,6 +520,156 @@
 	amdgpu_command_submission_copy_linear_helper(AMDGPU_HW_IP_GFX);
 }
 
+static void amdgpu_bo_eviction_test(void)
+{
+	const int sdma_write_length = 1024;
+	const int pm4_dw = 256;
+	amdgpu_context_handle context_handle;
+	amdgpu_bo_handle bo1, bo2, vram_max[2], gtt_max[2];
+	amdgpu_bo_handle *resources;
+	uint32_t *pm4;
+	struct amdgpu_cs_ib_info *ib_info;
+	struct amdgpu_cs_request *ibs_request;
+	uint64_t bo1_mc, bo2_mc;
+	volatile unsigned char *bo1_cpu, *bo2_cpu;
+	int i, j, r, loop1, loop2;
+	uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
+	amdgpu_va_handle bo1_va_handle, bo2_va_handle;
+	struct amdgpu_heap_info vram_info, gtt_info;
+
+	pm4 = calloc(pm4_dw, sizeof(*pm4));
+	CU_ASSERT_NOT_EQUAL(pm4, NULL);
+
+	ib_info = calloc(1, sizeof(*ib_info));
+	CU_ASSERT_NOT_EQUAL(ib_info, NULL);
+
+	ibs_request = calloc(1, sizeof(*ibs_request));
+	CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
+
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	/* prepare resource */
+	resources = calloc(4, sizeof(amdgpu_bo_handle));
+	CU_ASSERT_NOT_EQUAL(resources, NULL);
+
+	r = amdgpu_query_heap_info(device_handle, AMDGPU_GEM_DOMAIN_VRAM,
+				   0, &vram_info);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_alloc_wrap(device_handle, vram_info.max_allocation, 4096,
+				 AMDGPU_GEM_DOMAIN_VRAM, 0, &vram_max[0]);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_bo_alloc_wrap(device_handle, vram_info.max_allocation, 4096,
+				 AMDGPU_GEM_DOMAIN_VRAM, 0, &vram_max[1]);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_query_heap_info(device_handle, AMDGPU_GEM_DOMAIN_GTT,
+				   0, &gtt_info);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_alloc_wrap(device_handle, gtt_info.max_allocation, 4096,
+				 AMDGPU_GEM_DOMAIN_GTT, 0, &gtt_max[0]);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_bo_alloc_wrap(device_handle, gtt_info.max_allocation, 4096,
+				 AMDGPU_GEM_DOMAIN_GTT, 0, &gtt_max[1]);
+	CU_ASSERT_EQUAL(r, 0);
+
+
+
+	loop1 = loop2 = 0;
+	/* run 9 circle to test all mapping combination */
+	while(loop1 < 2) {
+		while(loop2 < 2) {
+			/* allocate UC bo1for sDMA use */
+			r = amdgpu_bo_alloc_and_map(device_handle,
+						    sdma_write_length, 4096,
+						    AMDGPU_GEM_DOMAIN_GTT,
+						    gtt_flags[loop1], &bo1,
+						    (void**)&bo1_cpu, &bo1_mc,
+						    &bo1_va_handle);
+			CU_ASSERT_EQUAL(r, 0);
+
+			/* set bo1 */
+			memset((void*)bo1_cpu, 0xaa, sdma_write_length);
+
+			/* allocate UC bo2 for sDMA use */
+			r = amdgpu_bo_alloc_and_map(device_handle,
+						    sdma_write_length, 4096,
+						    AMDGPU_GEM_DOMAIN_GTT,
+						    gtt_flags[loop2], &bo2,
+						    (void**)&bo2_cpu, &bo2_mc,
+						    &bo2_va_handle);
+			CU_ASSERT_EQUAL(r, 0);
+
+			/* clear bo2 */
+			memset((void*)bo2_cpu, 0, sdma_write_length);
+
+			resources[0] = bo1;
+			resources[1] = bo2;
+			resources[2] = vram_max[loop2];
+			resources[3] = gtt_max[loop2];
+
+			/* fulfill PM4: test DMA copy linear */
+			i = j = 0;
+			if (family_id == AMDGPU_FAMILY_SI) {
+				pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI, 0, 0, 0,
+							  sdma_write_length);
+				pm4[i++] = 0xffffffff & bo2_mc;
+				pm4[i++] = 0xffffffff & bo1_mc;
+				pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+				pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+			} else {
+				pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0);
+				if (family_id >= AMDGPU_FAMILY_AI)
+					pm4[i++] = sdma_write_length - 1;
+				else
+					pm4[i++] = sdma_write_length;
+				pm4[i++] = 0;
+				pm4[i++] = 0xffffffff & bo1_mc;
+				pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+				pm4[i++] = 0xffffffff & bo2_mc;
+				pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+			}
+
+			amdgpu_test_exec_cs_helper(context_handle,
+						   AMDGPU_HW_IP_DMA, 0,
+						   i, pm4,
+						   4, resources,
+						   ib_info, ibs_request);
+
+			/* verify if SDMA test result meets with expected */
+			i = 0;
+			while(i < sdma_write_length) {
+				CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa);
+			}
+			r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc,
+						     sdma_write_length);
+			CU_ASSERT_EQUAL(r, 0);
+			r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc,
+						     sdma_write_length);
+			CU_ASSERT_EQUAL(r, 0);
+			loop2++;
+		}
+		loop2 = 0;
+		loop1++;
+	}
+	amdgpu_bo_free(vram_max[0]);
+	amdgpu_bo_free(vram_max[1]);
+	amdgpu_bo_free(gtt_max[0]);
+	amdgpu_bo_free(gtt_max[1]);
+	/* clean resources */
+	free(resources);
+	free(ibs_request);
+	free(ib_info);
+	free(pm4);
+
+	/* end of test */
+	r = amdgpu_cs_ctx_free(context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+}
+
+
 static void amdgpu_command_submission_gfx(void)
 {
 	/* write data using the CP */
@@ -493,10 +696,19 @@
 	struct amdgpu_cs_fence fence_status = {0};
 	uint32_t *ptr;
 	uint32_t expired;
+	uint32_t sdma_nop, gfx_nop;
 	amdgpu_bo_list_handle bo_list[2];
 	amdgpu_va_handle va_handle[2];
 	int r, i;
 
+	if (family_id == AMDGPU_FAMILY_SI) {
+		sdma_nop = SDMA_PACKET_SI(SDMA_NOP_SI, 0, 0, 0, 0);
+		gfx_nop = GFX_COMPUTE_NOP_SI;
+	} else {
+		sdma_nop = SDMA_PKT_HEADER_OP(SDMA_NOP);
+		gfx_nop = GFX_COMPUTE_NOP;
+	}
+
 	r = amdgpu_cs_create_semaphore(&sem);
 	CU_ASSERT_EQUAL(r, 0);
 	for (i = 0; i < 2; i++) {
@@ -516,7 +728,7 @@
 
 	/* 1. same context different engine */
 	ptr = ib_result_cpu[0];
-	ptr[0] = SDMA_NOP;
+	ptr[0] = sdma_nop;
 	ib_info[0].ib_mc_address = ib_result_mc_address[0];
 	ib_info[0].size = 1;
 
@@ -533,7 +745,7 @@
 	r = amdgpu_cs_wait_semaphore(context_handle[0], AMDGPU_HW_IP_GFX, 0, 0, sem);
 	CU_ASSERT_EQUAL(r, 0);
 	ptr = ib_result_cpu[1];
-	ptr[0] = GFX_COMPUTE_NOP;
+	ptr[0] = gfx_nop;
 	ib_info[1].ib_mc_address = ib_result_mc_address[1];
 	ib_info[1].size = 1;
 
@@ -557,7 +769,7 @@
 
 	/* 2. same engine different context */
 	ptr = ib_result_cpu[0];
-	ptr[0] = GFX_COMPUTE_NOP;
+	ptr[0] = gfx_nop;
 	ib_info[0].ib_mc_address = ib_result_mc_address[0];
 	ib_info[0].size = 1;
 
@@ -574,7 +786,7 @@
 	r = amdgpu_cs_wait_semaphore(context_handle[1], AMDGPU_HW_IP_GFX, 0, 0, sem);
 	CU_ASSERT_EQUAL(r, 0);
 	ptr = ib_result_cpu[1];
-	ptr[0] = GFX_COMPUTE_NOP;
+	ptr[0] = gfx_nop;
 	ib_info[1].ib_mc_address = ib_result_mc_address[1];
 	ib_info[1].size = 1;
 
@@ -595,6 +807,7 @@
 					 500000000, 0, &expired);
 	CU_ASSERT_EQUAL(r, 0);
 	CU_ASSERT_EQUAL(expired, true);
+
 	for (i = 0; i < 2; i++) {
 		r = amdgpu_bo_unmap_and_free(ib_result_handle[i], va_handle[i],
 					     ib_result_mc_address[i], 4096);
@@ -622,14 +835,18 @@
 	struct amdgpu_cs_fence fence_status;
 	uint32_t *ptr;
 	uint32_t expired;
-	int i, r, instance;
+	int r, instance;
 	amdgpu_bo_list_handle bo_list;
 	amdgpu_va_handle va_handle;
+	struct drm_amdgpu_info_hw_ip info;
+
+	r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_COMPUTE, 0, &info);
+	CU_ASSERT_EQUAL(r, 0);
 
 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
 	CU_ASSERT_EQUAL(r, 0);
 
-	for (instance = 0; instance < 8; instance++) {
+	for (instance = 0; (1 << instance) & info.available_rings; instance++) {
 		r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
 					    AMDGPU_GEM_DOMAIN_GTT, 0,
 					    &ib_result_handle, &ib_result_cpu,
@@ -641,8 +858,8 @@
 		CU_ASSERT_EQUAL(r, 0);
 
 		ptr = ib_result_cpu;
-		for (i = 0; i < 16; ++i)
-			ptr[i] = 0xffff1000;
+		memset(ptr, 0, 16);
+		ptr[0]=PACKET3(PACKET3_NOP, 14);
 
 		memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
 		ib_info.ib_mc_address = ib_result_mc_address;
@@ -805,9 +1022,10 @@
 	struct amdgpu_cs_request *ibs_request;
 	uint64_t bo_mc;
 	volatile uint32_t *bo_cpu;
-	int i, j, r, loop;
+	int i, j, r, loop, ring_id;
 	uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
 	amdgpu_va_handle va_handle;
+	struct drm_amdgpu_info_hw_ip hw_ip_info;
 
 	pm4 = calloc(pm4_dw, sizeof(*pm4));
 	CU_ASSERT_NOT_EQUAL(pm4, NULL);
@@ -818,6 +1036,9 @@
 	ibs_request = calloc(1, sizeof(*ibs_request));
 	CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
 
+	r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info);
+	CU_ASSERT_EQUAL(r, 0);
+
 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
 	CU_ASSERT_EQUAL(r, 0);
 
@@ -825,58 +1046,66 @@
 	resources = calloc(1, sizeof(amdgpu_bo_handle));
 	CU_ASSERT_NOT_EQUAL(resources, NULL);
 
-	loop = 0;
-	while(loop < 2) {
-		/* allocate UC bo for sDMA use */
-		r = amdgpu_bo_alloc_and_map(device_handle,
-					    sdma_write_length * sizeof(uint32_t),
-					    4096, AMDGPU_GEM_DOMAIN_GTT,
-					    gtt_flags[loop], &bo, (void**)&bo_cpu,
-					    &bo_mc, &va_handle);
-		CU_ASSERT_EQUAL(r, 0);
+	for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) {
+		loop = 0;
+		while(loop < 2) {
+			/* allocate UC bo for sDMA use */
+			r = amdgpu_bo_alloc_and_map(device_handle,
+						    sdma_write_length * sizeof(uint32_t),
+						    4096, AMDGPU_GEM_DOMAIN_GTT,
+						    gtt_flags[loop], &bo, (void**)&bo_cpu,
+						    &bo_mc, &va_handle);
+			CU_ASSERT_EQUAL(r, 0);
 
-		/* clear bo */
-		memset((void*)bo_cpu, 0, sdma_write_length * sizeof(uint32_t));
+			/* clear bo */
+			memset((void*)bo_cpu, 0, sdma_write_length * sizeof(uint32_t));
 
+			resources[0] = bo;
 
-		resources[0] = bo;
+			/* fulfill PM4: test DMA write-linear */
+			i = j = 0;
+			if (ip_type == AMDGPU_HW_IP_DMA) {
+				if (family_id == AMDGPU_FAMILY_SI)
+					pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_WRITE, 0, 0, 0,
+								  sdma_write_length);
+				else
+					pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
+							       SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
+				pm4[i++] = 0xffffffff & bo_mc;
+				pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+				if (family_id >= AMDGPU_FAMILY_AI)
+					pm4[i++] = sdma_write_length - 1;
+				else if (family_id != AMDGPU_FAMILY_SI)
+					pm4[i++] = sdma_write_length;
+				while(j++ < sdma_write_length)
+					pm4[i++] = 0xdeadbeaf;
+			} else if ((ip_type == AMDGPU_HW_IP_GFX) ||
+				    (ip_type == AMDGPU_HW_IP_COMPUTE)) {
+				pm4[i++] = PACKET3(PACKET3_WRITE_DATA, 2 + sdma_write_length);
+				pm4[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM;
+				pm4[i++] = 0xfffffffc & bo_mc;
+				pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+				while(j++ < sdma_write_length)
+					pm4[i++] = 0xdeadbeaf;
+			}
 
-		/* fulfill PM4: test DMA write-linear */
-		i = j = 0;
-		if (ip_type == AMDGPU_HW_IP_DMA) {
-			pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
-					       SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
-			pm4[i++] = 0xffffffff & bo_mc;
-			pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
-			pm4[i++] = sdma_write_length;
-			while(j++ < sdma_write_length)
-				pm4[i++] = 0xdeadbeaf;
-		} else if ((ip_type == AMDGPU_HW_IP_GFX) ||
-			   (ip_type == AMDGPU_HW_IP_COMPUTE)) {
-			pm4[i++] = PACKET3(PACKET3_WRITE_DATA, 2 + sdma_write_length);
-			pm4[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM;
-			pm4[i++] = 0xfffffffc & bo_mc;
-			pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
-			while(j++ < sdma_write_length)
-				pm4[i++] = 0xdeadbeaf;
+			amdgpu_test_exec_cs_helper(context_handle,
+						   ip_type, ring_id,
+						   i, pm4,
+						   1, resources,
+						   ib_info, ibs_request);
+
+			/* verify if SDMA test result meets with expected */
+			i = 0;
+			while(i < sdma_write_length) {
+				CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf);
+			}
+
+			r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc,
+						     sdma_write_length * sizeof(uint32_t));
+			CU_ASSERT_EQUAL(r, 0);
+			loop++;
 		}
-
-		amdgpu_test_exec_cs_helper(context_handle,
-					   ip_type, 0,
-					   i, pm4,
-					   1, resources,
-					   ib_info, ibs_request);
-
-		/* verify if SDMA test result meets with expected */
-		i = 0;
-		while(i < sdma_write_length) {
-			CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf);
-		}
-
-		r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc,
-					     sdma_write_length * sizeof(uint32_t));
-		CU_ASSERT_EQUAL(r, 0);
-		loop++;
 	}
 	/* clean resources */
 	free(resources);
@@ -906,9 +1135,10 @@
 	struct amdgpu_cs_request *ibs_request;
 	uint64_t bo_mc;
 	volatile uint32_t *bo_cpu;
-	int i, j, r, loop;
+	int i, j, r, loop, ring_id;
 	uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
 	amdgpu_va_handle va_handle;
+	struct drm_amdgpu_info_hw_ip hw_ip_info;
 
 	pm4 = calloc(pm4_dw, sizeof(*pm4));
 	CU_ASSERT_NOT_EQUAL(pm4, NULL);
@@ -919,6 +1149,9 @@
 	ibs_request = calloc(1, sizeof(*ibs_request));
 	CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
 
+	r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info);
+	CU_ASSERT_EQUAL(r, 0);
+
 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
 	CU_ASSERT_EQUAL(r, 0);
 
@@ -926,60 +1159,86 @@
 	resources = calloc(1, sizeof(amdgpu_bo_handle));
 	CU_ASSERT_NOT_EQUAL(resources, NULL);
 
-	loop = 0;
-	while(loop < 2) {
-		/* allocate UC bo for sDMA use */
-		r = amdgpu_bo_alloc_and_map(device_handle,
-					    sdma_write_length, 4096,
-					    AMDGPU_GEM_DOMAIN_GTT,
-					    gtt_flags[loop], &bo, (void**)&bo_cpu,
-					    &bo_mc, &va_handle);
-		CU_ASSERT_EQUAL(r, 0);
+	for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) {
+		loop = 0;
+		while(loop < 2) {
+			/* allocate UC bo for sDMA use */
+			r = amdgpu_bo_alloc_and_map(device_handle,
+						    sdma_write_length, 4096,
+						    AMDGPU_GEM_DOMAIN_GTT,
+						    gtt_flags[loop], &bo, (void**)&bo_cpu,
+						    &bo_mc, &va_handle);
+			CU_ASSERT_EQUAL(r, 0);
 
-		/* clear bo */
-		memset((void*)bo_cpu, 0, sdma_write_length);
+			/* clear bo */
+			memset((void*)bo_cpu, 0, sdma_write_length);
 
-		resources[0] = bo;
+			resources[0] = bo;
 
-		/* fulfill PM4: test DMA const fill */
-		i = j = 0;
-		if (ip_type == AMDGPU_HW_IP_DMA) {
-			pm4[i++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0,
-					       SDMA_CONSTANT_FILL_EXTRA_SIZE(2));
-			pm4[i++] = 0xffffffff & bo_mc;
-			pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
-			pm4[i++] = 0xdeadbeaf;
-			pm4[i++] = sdma_write_length;
-		} else if ((ip_type == AMDGPU_HW_IP_GFX) ||
-			   (ip_type == AMDGPU_HW_IP_COMPUTE)) {
-			pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5);
-			pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) |
-				PACKET3_DMA_DATA_DST_SEL(0) |
-				PACKET3_DMA_DATA_SRC_SEL(2) |
-				PACKET3_DMA_DATA_CP_SYNC;
-			pm4[i++] = 0xdeadbeaf;
-			pm4[i++] = 0;
-			pm4[i++] = 0xfffffffc & bo_mc;
-			pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
-			pm4[i++] = sdma_write_length;
+			/* fulfill PM4: test DMA const fill */
+			i = j = 0;
+			if (ip_type == AMDGPU_HW_IP_DMA) {
+				if (family_id == AMDGPU_FAMILY_SI) {
+					pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_CONSTANT_FILL_SI,
+								  0, 0, 0,
+								  sdma_write_length / 4);
+					pm4[i++] = 0xfffffffc & bo_mc;
+					pm4[i++] = 0xdeadbeaf;
+					pm4[i++] = (0xffffffff00000000 & bo_mc) >> 16;
+				} else {
+					pm4[i++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0,
+							       SDMA_CONSTANT_FILL_EXTRA_SIZE(2));
+					pm4[i++] = 0xffffffff & bo_mc;
+					pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+					pm4[i++] = 0xdeadbeaf;
+					if (family_id >= AMDGPU_FAMILY_AI)
+						pm4[i++] = sdma_write_length - 1;
+					else
+						pm4[i++] = sdma_write_length;
+				}
+			} else if ((ip_type == AMDGPU_HW_IP_GFX) ||
+				   (ip_type == AMDGPU_HW_IP_COMPUTE)) {
+				if (family_id == AMDGPU_FAMILY_SI) {
+					pm4[i++] = PACKET3(PACKET3_DMA_DATA_SI, 4);
+					pm4[i++] = 0xdeadbeaf;
+					pm4[i++] = PACKET3_DMA_DATA_SI_ENGINE(0) |
+						   PACKET3_DMA_DATA_SI_DST_SEL(0) |
+						   PACKET3_DMA_DATA_SI_SRC_SEL(2) |
+						   PACKET3_DMA_DATA_SI_CP_SYNC;
+					pm4[i++] = 0xffffffff & bo_mc;
+					pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+					pm4[i++] = sdma_write_length;
+				} else {
+					pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5);
+					pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) |
+						   PACKET3_DMA_DATA_DST_SEL(0) |
+						   PACKET3_DMA_DATA_SRC_SEL(2) |
+						   PACKET3_DMA_DATA_CP_SYNC;
+					pm4[i++] = 0xdeadbeaf;
+					pm4[i++] = 0;
+					pm4[i++] = 0xfffffffc & bo_mc;
+					pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
+					pm4[i++] = sdma_write_length;
+				}
+			}
+
+			amdgpu_test_exec_cs_helper(context_handle,
+						   ip_type, ring_id,
+						   i, pm4,
+						   1, resources,
+						   ib_info, ibs_request);
+
+			/* verify if SDMA test result meets with expected */
+			i = 0;
+			while(i < (sdma_write_length / 4)) {
+				CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf);
+			}
+
+			r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc,
+						     sdma_write_length);
+			CU_ASSERT_EQUAL(r, 0);
+			loop++;
 		}
-
-		amdgpu_test_exec_cs_helper(context_handle,
-					   ip_type, 0,
-					   i, pm4,
-					   1, resources,
-					   ib_info, ibs_request);
-
-		/* verify if SDMA test result meets with expected */
-		i = 0;
-		while(i < (sdma_write_length / 4)) {
-			CU_ASSERT_EQUAL(bo_cpu[i++], 0xdeadbeaf);
-		}
-
-		r = amdgpu_bo_unmap_and_free(bo, va_handle, bo_mc,
-					     sdma_write_length);
-		CU_ASSERT_EQUAL(r, 0);
-		loop++;
 	}
 	/* clean resources */
 	free(resources);
@@ -1009,9 +1268,10 @@
 	struct amdgpu_cs_request *ibs_request;
 	uint64_t bo1_mc, bo2_mc;
 	volatile unsigned char *bo1_cpu, *bo2_cpu;
-	int i, j, r, loop1, loop2;
+	int i, j, r, loop1, loop2, ring_id;
 	uint64_t gtt_flags[2] = {0, AMDGPU_GEM_CREATE_CPU_GTT_USWC};
 	amdgpu_va_handle bo1_va_handle, bo2_va_handle;
+	struct drm_amdgpu_info_hw_ip hw_ip_info;
 
 	pm4 = calloc(pm4_dw, sizeof(*pm4));
 	CU_ASSERT_NOT_EQUAL(pm4, NULL);
@@ -1022,6 +1282,9 @@
 	ibs_request = calloc(1, sizeof(*ibs_request));
 	CU_ASSERT_NOT_EQUAL(ibs_request, NULL);
 
+	r = amdgpu_query_hw_ip_info(device_handle, ip_type, 0, &hw_ip_info);
+	CU_ASSERT_EQUAL(r, 0);
+
 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
 	CU_ASSERT_EQUAL(r, 0);
 
@@ -1029,81 +1292,111 @@
 	resources = calloc(2, sizeof(amdgpu_bo_handle));
 	CU_ASSERT_NOT_EQUAL(resources, NULL);
 
-	loop1 = loop2 = 0;
-	/* run 9 circle to test all mapping combination */
-	while(loop1 < 2) {
-		while(loop2 < 2) {
-			/* allocate UC bo1for sDMA use */
-			r = amdgpu_bo_alloc_and_map(device_handle,
-						    sdma_write_length, 4096,
-						    AMDGPU_GEM_DOMAIN_GTT,
-						    gtt_flags[loop1], &bo1,
-						    (void**)&bo1_cpu, &bo1_mc,
-						    &bo1_va_handle);
-			CU_ASSERT_EQUAL(r, 0);
+	for (ring_id = 0; (1 << ring_id) & hw_ip_info.available_rings; ring_id++) {
+		loop1 = loop2 = 0;
+		/* run 9 circle to test all mapping combination */
+		while(loop1 < 2) {
+			while(loop2 < 2) {
+				/* allocate UC bo1for sDMA use */
+				r = amdgpu_bo_alloc_and_map(device_handle,
+							    sdma_write_length, 4096,
+							    AMDGPU_GEM_DOMAIN_GTT,
+							    gtt_flags[loop1], &bo1,
+							    (void**)&bo1_cpu, &bo1_mc,
+							    &bo1_va_handle);
+				CU_ASSERT_EQUAL(r, 0);
 
-			/* set bo1 */
-			memset((void*)bo1_cpu, 0xaa, sdma_write_length);
+				/* set bo1 */
+				memset((void*)bo1_cpu, 0xaa, sdma_write_length);
 
-			/* allocate UC bo2 for sDMA use */
-			r = amdgpu_bo_alloc_and_map(device_handle,
-						    sdma_write_length, 4096,
-						    AMDGPU_GEM_DOMAIN_GTT,
-						    gtt_flags[loop2], &bo2,
-						    (void**)&bo2_cpu, &bo2_mc,
-						    &bo2_va_handle);
-			CU_ASSERT_EQUAL(r, 0);
+				/* allocate UC bo2 for sDMA use */
+				r = amdgpu_bo_alloc_and_map(device_handle,
+							    sdma_write_length, 4096,
+							    AMDGPU_GEM_DOMAIN_GTT,
+							    gtt_flags[loop2], &bo2,
+							    (void**)&bo2_cpu, &bo2_mc,
+							    &bo2_va_handle);
+				CU_ASSERT_EQUAL(r, 0);
 
-			/* clear bo2 */
-			memset((void*)bo2_cpu, 0, sdma_write_length);
+				/* clear bo2 */
+				memset((void*)bo2_cpu, 0, sdma_write_length);
 
-			resources[0] = bo1;
-			resources[1] = bo2;
+				resources[0] = bo1;
+				resources[1] = bo2;
 
-			/* fulfill PM4: test DMA copy linear */
-			i = j = 0;
-			if (ip_type == AMDGPU_HW_IP_DMA) {
-				pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0);
-				pm4[i++] = sdma_write_length;
-				pm4[i++] = 0;
-				pm4[i++] = 0xffffffff & bo1_mc;
-				pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
-				pm4[i++] = 0xffffffff & bo2_mc;
-				pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
-			} else if ((ip_type == AMDGPU_HW_IP_GFX) ||
-				   (ip_type == AMDGPU_HW_IP_COMPUTE)) {
-				pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5);
-				pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) |
-					PACKET3_DMA_DATA_DST_SEL(0) |
-					PACKET3_DMA_DATA_SRC_SEL(0) |
-					PACKET3_DMA_DATA_CP_SYNC;
-				pm4[i++] = 0xfffffffc & bo1_mc;
-				pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
-				pm4[i++] = 0xfffffffc & bo2_mc;
-				pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
-				pm4[i++] = sdma_write_length;
+				/* fulfill PM4: test DMA copy linear */
+				i = j = 0;
+				if (ip_type == AMDGPU_HW_IP_DMA) {
+					if (family_id == AMDGPU_FAMILY_SI) {
+						pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_COPY_SI,
+									  0, 0, 0,
+									  sdma_write_length);
+						pm4[i++] = 0xffffffff & bo2_mc;
+						pm4[i++] = 0xffffffff & bo1_mc;
+						pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+						pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+					} else {
+						pm4[i++] = SDMA_PACKET(SDMA_OPCODE_COPY,
+								       SDMA_COPY_SUB_OPCODE_LINEAR,
+								       0);
+						if (family_id >= AMDGPU_FAMILY_AI)
+							pm4[i++] = sdma_write_length - 1;
+						else
+							pm4[i++] = sdma_write_length;
+						pm4[i++] = 0;
+						pm4[i++] = 0xffffffff & bo1_mc;
+						pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+						pm4[i++] = 0xffffffff & bo2_mc;
+						pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+					}
+				} else if ((ip_type == AMDGPU_HW_IP_GFX) ||
+					   (ip_type == AMDGPU_HW_IP_COMPUTE)) {
+					if (family_id == AMDGPU_FAMILY_SI) {
+						pm4[i++] = PACKET3(PACKET3_DMA_DATA_SI, 4);
+						pm4[i++] = 0xfffffffc & bo1_mc;
+						pm4[i++] = PACKET3_DMA_DATA_SI_ENGINE(0) |
+							   PACKET3_DMA_DATA_SI_DST_SEL(0) |
+							   PACKET3_DMA_DATA_SI_SRC_SEL(0) |
+							   PACKET3_DMA_DATA_SI_CP_SYNC |
+							   (0xffff00000000 & bo1_mc) >> 32;
+						pm4[i++] = 0xfffffffc & bo2_mc;
+						pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+						pm4[i++] = sdma_write_length;
+					} else {
+						pm4[i++] = PACKET3(PACKET3_DMA_DATA, 5);
+						pm4[i++] = PACKET3_DMA_DATA_ENGINE(0) |
+							   PACKET3_DMA_DATA_DST_SEL(0) |
+							   PACKET3_DMA_DATA_SRC_SEL(0) |
+							   PACKET3_DMA_DATA_CP_SYNC;
+						pm4[i++] = 0xfffffffc & bo1_mc;
+						pm4[i++] = (0xffffffff00000000 & bo1_mc) >> 32;
+						pm4[i++] = 0xfffffffc & bo2_mc;
+						pm4[i++] = (0xffffffff00000000 & bo2_mc) >> 32;
+						pm4[i++] = sdma_write_length;
+					}
+				}
+
+				amdgpu_test_exec_cs_helper(context_handle,
+							   ip_type, ring_id,
+							   i, pm4,
+							   2, resources,
+							   ib_info, ibs_request);
+
+				/* verify if SDMA test result meets with expected */
+				i = 0;
+				while(i < sdma_write_length) {
+					CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa);
+				}
+				r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc,
+							     sdma_write_length);
+				CU_ASSERT_EQUAL(r, 0);
+				r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc,
+							     sdma_write_length);
+				CU_ASSERT_EQUAL(r, 0);
+				loop2++;
 			}
-
-			amdgpu_test_exec_cs_helper(context_handle,
-						   ip_type, 0,
-						   i, pm4,
-						   2, resources,
-						   ib_info, ibs_request);
-
-			/* verify if SDMA test result meets with expected */
-			i = 0;
-			while(i < sdma_write_length) {
-				CU_ASSERT_EQUAL(bo2_cpu[i++], 0xaa);
-			}
-			r = amdgpu_bo_unmap_and_free(bo1, bo1_va_handle, bo1_mc,
-						     sdma_write_length);
-			CU_ASSERT_EQUAL(r, 0);
-			r = amdgpu_bo_unmap_and_free(bo2, bo2_va_handle, bo2_mc,
-						     sdma_write_length);
-			CU_ASSERT_EQUAL(r, 0);
-			loop2++;
+			loop1++;
 		}
-		loop1++;
 	}
 	/* clean resources */
 	free(resources);
@@ -1128,6 +1421,106 @@
 	amdgpu_command_submission_sdma_copy_linear();
 }
 
+static void amdgpu_command_submission_multi_fence_wait_all(bool wait_all)
+{
+	amdgpu_context_handle context_handle;
+	amdgpu_bo_handle ib_result_handle, ib_result_ce_handle;
+	void *ib_result_cpu, *ib_result_ce_cpu;
+	uint64_t ib_result_mc_address, ib_result_ce_mc_address;
+	struct amdgpu_cs_request ibs_request[2] = {0};
+	struct amdgpu_cs_ib_info ib_info[2];
+	struct amdgpu_cs_fence fence_status[2] = {0};
+	uint32_t *ptr;
+	uint32_t expired;
+	amdgpu_bo_list_handle bo_list;
+	amdgpu_va_handle va_handle, va_handle_ce;
+	int r;
+	int i = 0, ib_cs_num = 2;
+
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+				    AMDGPU_GEM_DOMAIN_GTT, 0,
+				    &ib_result_handle, &ib_result_cpu,
+				    &ib_result_mc_address, &va_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+				    AMDGPU_GEM_DOMAIN_GTT, 0,
+				    &ib_result_ce_handle, &ib_result_ce_cpu,
+				    &ib_result_ce_mc_address, &va_handle_ce);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_get_bo_list(device_handle, ib_result_handle,
+			       ib_result_ce_handle, &bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	memset(ib_info, 0, 2 * sizeof(struct amdgpu_cs_ib_info));
+
+	/* IT_SET_CE_DE_COUNTERS */
+	ptr = ib_result_ce_cpu;
+	if (family_id != AMDGPU_FAMILY_SI) {
+		ptr[i++] = 0xc0008900;
+		ptr[i++] = 0;
+	}
+	ptr[i++] = 0xc0008400;
+	ptr[i++] = 1;
+	ib_info[0].ib_mc_address = ib_result_ce_mc_address;
+	ib_info[0].size = i;
+	ib_info[0].flags = AMDGPU_IB_FLAG_CE;
+
+	/* IT_WAIT_ON_CE_COUNTER */
+	ptr = ib_result_cpu;
+	ptr[0] = 0xc0008600;
+	ptr[1] = 0x00000001;
+	ib_info[1].ib_mc_address = ib_result_mc_address;
+	ib_info[1].size = 2;
+
+	for (i = 0; i < ib_cs_num; i++) {
+		ibs_request[i].ip_type = AMDGPU_HW_IP_GFX;
+		ibs_request[i].number_of_ibs = 2;
+		ibs_request[i].ibs = ib_info;
+		ibs_request[i].resources = bo_list;
+		ibs_request[i].fence_info.handle = NULL;
+	}
+
+	r = amdgpu_cs_submit(context_handle, 0,ibs_request, ib_cs_num);
+
+	CU_ASSERT_EQUAL(r, 0);
+
+	for (i = 0; i < ib_cs_num; i++) {
+		fence_status[i].context = context_handle;
+		fence_status[i].ip_type = AMDGPU_HW_IP_GFX;
+		fence_status[i].fence = ibs_request[i].seq_no;
+	}
+
+	r = amdgpu_cs_wait_fences(fence_status, ib_cs_num, wait_all,
+				AMDGPU_TIMEOUT_INFINITE,
+				&expired, NULL);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+				     ib_result_mc_address, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_unmap_and_free(ib_result_ce_handle, va_handle_ce,
+				     ib_result_ce_mc_address, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_list_destroy(bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_cs_ctx_free(context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_command_submission_multi_fence(void)
+{
+	amdgpu_command_submission_multi_fence_wait_all(true);
+	amdgpu_command_submission_multi_fence_wait_all(false);
+}
+
 static void amdgpu_userptr_test(void)
 {
 	int i, r, j;
@@ -1175,15 +1568,28 @@
 	handle = buf_handle;
 
 	j = i = 0;
-	pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
-			       SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
+
+	if (family_id == AMDGPU_FAMILY_SI)
+		pm4[i++] = SDMA_PACKET_SI(SDMA_OPCODE_WRITE, 0, 0, 0,
+				sdma_write_length);
+	else
+		pm4[i++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
+				SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
 	pm4[i++] = 0xffffffff & bo_mc;
 	pm4[i++] = (0xffffffff00000000 & bo_mc) >> 32;
-	pm4[i++] = sdma_write_length;
+	if (family_id >= AMDGPU_FAMILY_AI)
+		pm4[i++] = sdma_write_length - 1;
+	else if (family_id != AMDGPU_FAMILY_SI)
+		pm4[i++] = sdma_write_length;
 
 	while (j++ < sdma_write_length)
 		pm4[i++] = 0xdeadbeaf;
 
+	if (!fork()) {
+		pm4[0] = 0x0;
+		exit(0);
+	}
+
 	amdgpu_test_exec_cs_helper(context_handle,
 				   AMDGPU_HW_IP_DMA, 0,
 				   i, pm4,
@@ -1207,4 +1613,212 @@
 
 	r = amdgpu_cs_ctx_free(context_handle);
 	CU_ASSERT_EQUAL(r, 0);
+
+	wait(NULL);
+}
+
+static void amdgpu_sync_dependency_test(void)
+{
+	amdgpu_context_handle context_handle[2];
+	amdgpu_bo_handle ib_result_handle;
+	void *ib_result_cpu;
+	uint64_t ib_result_mc_address;
+	struct amdgpu_cs_request ibs_request;
+	struct amdgpu_cs_ib_info ib_info;
+	struct amdgpu_cs_fence fence_status;
+	uint32_t expired;
+	int i, j, r;
+	amdgpu_bo_list_handle bo_list;
+	amdgpu_va_handle va_handle;
+	static uint32_t *ptr;
+	uint64_t seq_no;
+
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle[0]);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle[1]);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_alloc_and_map(device_handle, 8192, 4096,
+			AMDGPU_GEM_DOMAIN_GTT, 0,
+						    &ib_result_handle, &ib_result_cpu,
+						    &ib_result_mc_address, &va_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+			       &bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	ptr = ib_result_cpu;
+	i = 0;
+
+	memcpy(ptr + CODE_OFFSET , shader_bin, sizeof(shader_bin));
+
+	/* Dispatch minimal init config and verify it's executed */
+	ptr[i++] = PACKET3(PKT3_CONTEXT_CONTROL, 1);
+	ptr[i++] = 0x80000000;
+	ptr[i++] = 0x80000000;
+
+	ptr[i++] = PACKET3(PKT3_CLEAR_STATE, 0);
+	ptr[i++] = 0x80000000;
+
+
+	/* Program compute regs */
+	ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2);
+	ptr[i++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START;
+	ptr[i++] = (ib_result_mc_address + CODE_OFFSET * 4) >> 8;
+	ptr[i++] = (ib_result_mc_address + CODE_OFFSET * 4) >> 40;
+
+
+	ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2);
+	ptr[i++] = mmCOMPUTE_PGM_RSRC1 - PACKET3_SET_SH_REG_START;
+	/*
+	 * 002c0040         COMPUTE_PGM_RSRC1 <- VGPRS = 0
+	                                      SGPRS = 1
+	                                      PRIORITY = 0
+	                                      FLOAT_MODE = 192 (0xc0)
+	                                      PRIV = 0
+	                                      DX10_CLAMP = 1
+	                                      DEBUG_MODE = 0
+	                                      IEEE_MODE = 0
+	                                      BULKY = 0
+	                                      CDBG_USER = 0
+	 *
+	 */
+	ptr[i++] = 0x002c0040;
+
+
+	/*
+	 * 00000010         COMPUTE_PGM_RSRC2 <- SCRATCH_EN = 0
+	                                      USER_SGPR = 8
+	                                      TRAP_PRESENT = 0
+	                                      TGID_X_EN = 0
+	                                      TGID_Y_EN = 0
+	                                      TGID_Z_EN = 0
+	                                      TG_SIZE_EN = 0
+	                                      TIDIG_COMP_CNT = 0
+	                                      EXCP_EN_MSB = 0
+	                                      LDS_SIZE = 0
+	                                      EXCP_EN = 0
+	 *
+	 */
+	ptr[i++] = 0x00000010;
+
+
+/*
+ * 00000100         COMPUTE_TMPRING_SIZE <- WAVES = 256 (0x100)
+                                         WAVESIZE = 0
+ *
+ */
+	ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1);
+	ptr[i++] = mmCOMPUTE_TMPRING_SIZE - PACKET3_SET_SH_REG_START;
+	ptr[i++] = 0x00000100;
+
+	ptr[i++] = PACKET3(PKT3_SET_SH_REG, 2);
+	ptr[i++] = mmCOMPUTE_USER_DATA_0 - PACKET3_SET_SH_REG_START;
+	ptr[i++] = 0xffffffff & (ib_result_mc_address + DATA_OFFSET * 4);
+	ptr[i++] = (0xffffffff00000000 & (ib_result_mc_address + DATA_OFFSET * 4)) >> 32;
+
+	ptr[i++] = PACKET3(PKT3_SET_SH_REG, 1);
+	ptr[i++] = mmCOMPUTE_RESOURCE_LIMITS - PACKET3_SET_SH_REG_START;
+	ptr[i++] = 0;
+
+	ptr[i++] = PACKET3(PKT3_SET_SH_REG, 3);
+	ptr[i++] = mmCOMPUTE_NUM_THREAD_X - PACKET3_SET_SH_REG_START;
+	ptr[i++] = 1;
+	ptr[i++] = 1;
+	ptr[i++] = 1;
+
+
+	/* Dispatch */
+	ptr[i++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
+	ptr[i++] = 1;
+	ptr[i++] = 1;
+	ptr[i++] = 1;
+	ptr[i++] = 0x00000045; /* DISPATCH DIRECT field */
+
+
+	while (i & 7)
+		ptr[i++] =  0xffff1000; /* type3 nop packet */
+
+	memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+	ib_info.ib_mc_address = ib_result_mc_address;
+	ib_info.size = i;
+
+	memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+	ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+	ibs_request.ring = 0;
+	ibs_request.number_of_ibs = 1;
+	ibs_request.ibs = &ib_info;
+	ibs_request.resources = bo_list;
+	ibs_request.fence_info.handle = NULL;
+
+	r = amdgpu_cs_submit(context_handle[1], 0,&ibs_request, 1);
+	CU_ASSERT_EQUAL(r, 0);
+	seq_no = ibs_request.seq_no;
+
+
+
+	/* Prepare second command with dependency on the first */
+	j = i;
+	ptr[i++] = PACKET3(PACKET3_WRITE_DATA, 3);
+	ptr[i++] = WRITE_DATA_DST_SEL(5) | WR_CONFIRM;
+	ptr[i++] =          0xfffffffc & (ib_result_mc_address + DATA_OFFSET * 4);
+	ptr[i++] = (0xffffffff00000000 & (ib_result_mc_address + DATA_OFFSET * 4)) >> 32;
+	ptr[i++] = 99;
+
+	while (i & 7)
+		ptr[i++] =  0xffff1000; /* type3 nop packet */
+
+	memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+	ib_info.ib_mc_address = ib_result_mc_address + j * 4;
+	ib_info.size = i - j;
+
+	memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+	ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+	ibs_request.ring = 0;
+	ibs_request.number_of_ibs = 1;
+	ibs_request.ibs = &ib_info;
+	ibs_request.resources = bo_list;
+	ibs_request.fence_info.handle = NULL;
+
+	ibs_request.number_of_dependencies = 1;
+
+	ibs_request.dependencies = calloc(1, sizeof(*ibs_request.dependencies));
+	ibs_request.dependencies[0].context = context_handle[1];
+	ibs_request.dependencies[0].ip_instance = 0;
+	ibs_request.dependencies[0].ring = 0;
+	ibs_request.dependencies[0].fence = seq_no;
+
+
+	r = amdgpu_cs_submit(context_handle[0], 0,&ibs_request, 1);
+	CU_ASSERT_EQUAL(r, 0);
+
+
+	memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+	fence_status.context = context_handle[0];
+	fence_status.ip_type = AMDGPU_HW_IP_GFX;
+	fence_status.ip_instance = 0;
+	fence_status.ring = 0;
+	fence_status.fence = ibs_request.seq_no;
+
+	r = amdgpu_cs_query_fence_status(&fence_status,
+		       AMDGPU_TIMEOUT_INFINITE,0, &expired);
+	CU_ASSERT_EQUAL(r, 0);
+
+	/* Expect the second command to wait for shader to complete */
+	CU_ASSERT_EQUAL(ptr[DATA_OFFSET], 99);
+
+	r = amdgpu_bo_list_destroy(bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+				     ib_result_mc_address, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_cs_ctx_free(context_handle[0]);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_cs_ctx_free(context_handle[1]);
+	CU_ASSERT_EQUAL(r, 0);
+
+	free(ibs_request.dependencies);
 }
diff --git a/tests/amdgpu/bo_tests.c b/tests/amdgpu/bo_tests.c
index 74b5e77..9d4da4a 100644
--- a/tests/amdgpu/bo_tests.c
+++ b/tests/amdgpu/bo_tests.c
@@ -21,10 +21,6 @@
  *
 */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdio.h>
 
 #include "CUnit/Basic.h"
@@ -46,13 +42,15 @@
 static void amdgpu_bo_export_import(void);
 static void amdgpu_bo_metadata(void);
 static void amdgpu_bo_map_unmap(void);
+static void amdgpu_memory_alloc(void);
+static void amdgpu_mem_fail_alloc(void);
 
 CU_TestInfo bo_tests[] = {
 	{ "Export/Import",  amdgpu_bo_export_import },
-#if 0
 	{ "Metadata",  amdgpu_bo_metadata },
-#endif
 	{ "CPU map/unmap",  amdgpu_bo_map_unmap },
+	{ "Memory alloc Test",  amdgpu_memory_alloc },
+	{ "Memory fail alloc Test",  amdgpu_mem_fail_alloc },
 	CU_TEST_INFO_NULL,
 };
 
@@ -195,3 +193,72 @@
 	r = amdgpu_bo_cpu_unmap(buffer_handle);
 	CU_ASSERT_EQUAL(r, 0);
 }
+
+static void amdgpu_memory_alloc(void)
+{
+	amdgpu_bo_handle bo;
+	amdgpu_va_handle va_handle;
+	uint64_t bo_mc;
+	int r;
+
+	/* Test visible VRAM */
+	bo = gpu_mem_alloc(device_handle,
+			4096, 4096,
+			AMDGPU_GEM_DOMAIN_VRAM,
+			AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+			&bo_mc, &va_handle);
+
+	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	/* Test invisible VRAM */
+	bo = gpu_mem_alloc(device_handle,
+			4096, 4096,
+			AMDGPU_GEM_DOMAIN_VRAM,
+			AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
+			&bo_mc, &va_handle);
+
+	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	/* Test GART Cacheable */
+	bo = gpu_mem_alloc(device_handle,
+			4096, 4096,
+			AMDGPU_GEM_DOMAIN_GTT,
+			0, &bo_mc, &va_handle);
+
+	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	/* Test GART USWC */
+	bo = gpu_mem_alloc(device_handle,
+			4096, 4096,
+			AMDGPU_GEM_DOMAIN_GTT,
+			AMDGPU_GEM_CREATE_CPU_GTT_USWC,
+			&bo_mc, &va_handle);
+
+	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_mem_fail_alloc(void)
+{
+	amdgpu_bo_handle bo;
+	int r;
+	struct amdgpu_bo_alloc_request req = {0};
+	amdgpu_bo_handle buf_handle;
+
+	/* Test impossible mem allocation, 1TB */
+	req.alloc_size = 0xE8D4A51000;
+	req.phys_alignment = 4096;
+	req.preferred_heap = AMDGPU_GEM_DOMAIN_VRAM;
+	req.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
+
+	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+	CU_ASSERT_EQUAL(r, -ENOMEM);
+
+	if (!r) {
+		r = amdgpu_bo_free(bo);
+		CU_ASSERT_EQUAL(r, 0);
+	}
+}
diff --git a/tests/amdgpu/cs_tests.c b/tests/amdgpu/cs_tests.c
index 82c55aa..7ad0f0d 100644
--- a/tests/amdgpu/cs_tests.c
+++ b/tests/amdgpu/cs_tests.c
@@ -21,10 +21,6 @@
  *
 */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdio.h>
 
 #include "CUnit/Basic.h"
@@ -32,7 +28,7 @@
 #include "util_math.h"
 
 #include "amdgpu_test.h"
-#include "uvd_messages.h"
+#include "decode_messages.h"
 #include "amdgpu_drm.h"
 #include "amdgpu_internal.h"
 
@@ -66,6 +62,26 @@
 	CU_TEST_INFO_NULL,
 };
 
+CU_BOOL suite_cs_tests_enable(void)
+{
+	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+					     &minor_version, &device_handle))
+		return CU_FALSE;
+
+	family_id = device_handle->info.family_id;
+
+	if (amdgpu_device_deinitialize(device_handle))
+		return CU_FALSE;
+
+
+	if (family_id >= AMDGPU_FAMILY_RV || family_id == AMDGPU_FAMILY_SI) {
+		printf("\n\nThe ASIC NOT support UVD, suite disabled\n");
+		return CU_FALSE;
+	}
+
+	return CU_TRUE;
+}
+
 int suite_cs_tests_init(void)
 {
 	amdgpu_bo_handle ib_result_handle;
@@ -175,11 +191,11 @@
 
 static void uvd_cmd(uint64_t addr, unsigned cmd, int *idx)
 {
-	ib_cpu[(*idx)++] = 0x3BC4;
+	ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC4 : 0x81C4;
 	ib_cpu[(*idx)++] = addr;
-	ib_cpu[(*idx)++] = 0x3BC5;
+	ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC5 : 0x81C5;
 	ib_cpu[(*idx)++] = addr >> 32;
-	ib_cpu[(*idx)++] = 0x3BC3;
+	ib_cpu[(*idx)++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC3 : 0x81C3;
 	ib_cpu[(*idx)++] = cmd << 1;
 }
 
@@ -211,10 +227,13 @@
 	CU_ASSERT_EQUAL(r, 0);
 
 	memcpy(msg, uvd_create_msg, sizeof(uvd_create_msg));
+
 	if (family_id >= AMDGPU_FAMILY_VI) {
 		((uint8_t*)msg)[0x10] = 7;
-		/* chip polaris 10/11 */
-		if (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A) {
+		/* chip beyond polaris 10/11 */
+		if ((family_id == AMDGPU_FAMILY_AI) ||
+		    (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+		     chip_id == chip_rev+0x64)) {
 			/* dpb size */
 			((uint8_t*)msg)[0x28] = 0x00;
 			((uint8_t*)msg)[0x29] = 0x94;
@@ -250,7 +269,7 @@
 
 static void amdgpu_cs_uvd_decode(void)
 {
-	const unsigned dpb_size = 15923584, ctx_size = 5287680, dt_size = 737280;
+	const unsigned dpb_size = 15923584, dt_size = 737280;
 	uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, ctx_addr, dt_addr, it_addr;
 	struct amdgpu_bo_alloc_request req = {0};
 	amdgpu_bo_handle buf_handle;
@@ -286,14 +305,18 @@
 	r = amdgpu_bo_cpu_map(buf_handle, (void **)&ptr);
 	CU_ASSERT_EQUAL(r, 0);
 
-	memcpy(ptr, uvd_decode_msg, sizeof(uvd_create_msg));
+	memcpy(ptr, uvd_decode_msg, sizeof(uvd_decode_msg));
+	memcpy(ptr + sizeof(uvd_decode_msg), avc_decode_msg, sizeof(avc_decode_msg));
+
 	if (family_id >= AMDGPU_FAMILY_VI) {
 		ptr[0x10] = 7;
 		ptr[0x98] = 0x00;
 		ptr[0x99] = 0x02;
-		/* chip polaris10/11 */
-		if (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A) {
-			/*dpb size */
+		/* chip beyond polaris10/11 */
+		if ((family_id == AMDGPU_FAMILY_AI) ||
+		    (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+		     chip_id == chip_rev+0x64)) {
+			/* dpb size */
 			ptr[0x24] = 0x00;
 			ptr[0x25] = 0x94;
 			ptr[0x26] = 0x6B;
@@ -335,9 +358,12 @@
 		bs_addr = fb_addr + 4*1024;
 	dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024);
 
-	if ((family_id >= AMDGPU_FAMILY_VI) &&
-		(chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A)) {
-		ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024);
+	if (family_id >= AMDGPU_FAMILY_VI) {
+		if ((family_id == AMDGPU_FAMILY_AI) ||
+		    (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+		     chip_id == chip_rev+0x64)) {
+			ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024);
+		}
 	}
 
 	dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024);
@@ -348,12 +374,16 @@
 	uvd_cmd(dt_addr, 0x2, &i);
 	uvd_cmd(fb_addr, 0x3, &i);
 	uvd_cmd(bs_addr, 0x100, &i);
+
 	if (family_id >= AMDGPU_FAMILY_VI) {
 		uvd_cmd(it_addr, 0x204, &i);
-		if (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A)
+		if ((family_id == AMDGPU_FAMILY_AI) ||
+		    (chip_id == chip_rev+0x50 || chip_id == chip_rev+0x5A ||
+		     chip_id == chip_rev+0x64))
 			uvd_cmd(ctx_addr, 0x206, &i);
-}
-	ib_cpu[i++] = 0x3BC6;
+	}
+
+	ib_cpu[i++] = (family_id < AMDGPU_FAMILY_AI) ? 0x3BC6 : 0x81C6;
 	ib_cpu[i++] = 0x1;
 	for (; i % 16; ++i)
 		ib_cpu[i] = 0x80000000;
@@ -364,7 +394,7 @@
 	/* TODO: use a real CRC32 */
 	for (i = 0, sum = 0; i < dt_size; ++i)
 		sum += ptr[i];
-	CU_ASSERT_EQUAL(sum, 0x20345d8);
+	CU_ASSERT_EQUAL(sum, SUM_DECODE);
 
 	r = amdgpu_bo_cpu_unmap(buf_handle);
 	CU_ASSERT_EQUAL(r, 0);
diff --git a/tests/amdgpu/deadlock_tests.c b/tests/amdgpu/deadlock_tests.c
new file mode 100644
index 0000000..1eb5761
--- /dev/null
+++ b/tests/amdgpu/deadlock_tests.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+#include <pthread.h>
+
+
+/*
+ * This defines the delay in MS after which memory location designated for
+ * compression against reference value is written to, unblocking command
+ * processor
+ */
+#define WRITE_MEM_ADDRESS_DELAY_MS 100
+
+#define	PACKET_TYPE3	3
+
+#define PACKET3(op, n)	((PACKET_TYPE3 << 30) |				\
+			 (((op) & 0xFF) << 8) |				\
+			 ((n) & 0x3FFF) << 16)
+
+#define	PACKET3_WAIT_REG_MEM				0x3C
+#define		WAIT_REG_MEM_FUNCTION(x)                ((x) << 0)
+		/* 0 - always
+		 * 1 - <
+		 * 2 - <=
+		 * 3 - ==
+		 * 4 - !=
+		 * 5 - >=
+		 * 6 - >
+		 */
+#define		WAIT_REG_MEM_MEM_SPACE(x)               ((x) << 4)
+		/* 0 - reg
+		 * 1 - mem
+		 */
+#define		WAIT_REG_MEM_OPERATION(x)               ((x) << 6)
+		/* 0 - wait_reg_mem
+		 * 1 - wr_wait_wr_reg
+		 */
+#define		WAIT_REG_MEM_ENGINE(x)                  ((x) << 8)
+		/* 0 - me
+		 * 1 - pfp
+		 */
+
+static  amdgpu_device_handle device_handle;
+static  uint32_t  major_version;
+static  uint32_t  minor_version;
+
+static pthread_t stress_thread;
+static uint32_t *ptr;
+
+static void amdgpu_deadlock_helper(unsigned ip_type);
+static void amdgpu_deadlock_gfx(void);
+static void amdgpu_deadlock_compute(void);
+
+CU_BOOL suite_deadlock_tests_enable(void)
+{
+	CU_BOOL enable = CU_TRUE;
+
+	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+					     &minor_version, &device_handle))
+		return CU_FALSE;
+
+	if (device_handle->info.family_id == AMDGPU_FAMILY_AI ||
+	    device_handle->info.family_id == AMDGPU_FAMILY_SI) {
+		printf("\n\nCurrently hangs the CP on this ASIC, deadlock suite disabled\n");
+		enable = CU_FALSE;
+	}
+
+	if (amdgpu_device_deinitialize(device_handle))
+		return CU_FALSE;
+
+	return enable;
+}
+
+int suite_deadlock_tests_init(void)
+{
+	int r;
+
+	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+				   &minor_version, &device_handle);
+
+	if (r) {
+		if ((r == -EACCES) && (errno == EACCES))
+			printf("\n\nError:%s. "
+				"Hint:Try to run this test program as root.",
+				strerror(errno));
+		return CUE_SINIT_FAILED;
+	}
+
+	return CUE_SUCCESS;
+}
+
+int suite_deadlock_tests_clean(void)
+{
+	int r = amdgpu_device_deinitialize(device_handle);
+
+	if (r == 0)
+		return CUE_SUCCESS;
+	else
+		return CUE_SCLEAN_FAILED;
+}
+
+
+CU_TestInfo deadlock_tests[] = {
+	{ "gfx ring block test",  amdgpu_deadlock_gfx },
+	{ "compute ring block test",  amdgpu_deadlock_compute },
+	CU_TEST_INFO_NULL,
+};
+
+static void *write_mem_address(void *data)
+{
+	int i;
+
+	/* useconds_t range is [0, 1,000,000] so use loop for waits > 1s */
+	for (i = 0; i < WRITE_MEM_ADDRESS_DELAY_MS; i++)
+		usleep(1000);
+
+	ptr[256] = 0x1;
+
+	return 0;
+}
+
+static void amdgpu_deadlock_gfx(void)
+{
+	amdgpu_deadlock_helper(AMDGPU_HW_IP_GFX);
+}
+
+static void amdgpu_deadlock_compute(void)
+{
+	amdgpu_deadlock_helper(AMDGPU_HW_IP_COMPUTE);
+}
+
+static void amdgpu_deadlock_helper(unsigned ip_type)
+{
+	amdgpu_context_handle context_handle;
+	amdgpu_bo_handle ib_result_handle;
+	void *ib_result_cpu;
+	uint64_t ib_result_mc_address;
+	struct amdgpu_cs_request ibs_request;
+	struct amdgpu_cs_ib_info ib_info;
+	struct amdgpu_cs_fence fence_status;
+	uint32_t expired;
+	int i, r;
+	amdgpu_bo_list_handle bo_list;
+	amdgpu_va_handle va_handle;
+
+	r = pthread_create(&stress_thread, NULL, write_mem_address, NULL);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+			AMDGPU_GEM_DOMAIN_GTT, 0,
+						    &ib_result_handle, &ib_result_cpu,
+						    &ib_result_mc_address, &va_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+			       &bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	ptr = ib_result_cpu;
+
+	ptr[0] = PACKET3(PACKET3_WAIT_REG_MEM, 5);
+	ptr[1] = (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
+			 WAIT_REG_MEM_FUNCTION(4) | /* != */
+			 WAIT_REG_MEM_ENGINE(0));  /* me */
+	ptr[2] = (ib_result_mc_address + 256*4) & 0xfffffffc;
+	ptr[3] = ((ib_result_mc_address + 256*4) >> 32) & 0xffffffff;
+	ptr[4] = 0x00000000; /* reference value */
+	ptr[5] = 0xffffffff; /* and mask */
+	ptr[6] = 0x00000004; /* poll interval */
+
+	for (i = 7; i < 16; ++i)
+		ptr[i] = 0xffff1000;
+
+
+	ptr[256] = 0x0; /* the memory we wait on to change */
+
+
+
+	memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+	ib_info.ib_mc_address = ib_result_mc_address;
+	ib_info.size = 16;
+
+	memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+	ibs_request.ip_type = ip_type;
+	ibs_request.ring = 0;
+	ibs_request.number_of_ibs = 1;
+	ibs_request.ibs = &ib_info;
+	ibs_request.resources = bo_list;
+	ibs_request.fence_info.handle = NULL;
+
+	for (i = 0; i < 200; i++) {
+		r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+		CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+	}
+
+	memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+	fence_status.context = context_handle;
+	fence_status.ip_type = ip_type;
+	fence_status.ip_instance = 0;
+	fence_status.ring = 0;
+	fence_status.fence = ibs_request.seq_no;
+
+	r = amdgpu_cs_query_fence_status(&fence_status,
+			AMDGPU_TIMEOUT_INFINITE,0, &expired);
+	CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1);
+
+	pthread_join(stress_thread, NULL);
+
+	r = amdgpu_bo_list_destroy(bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+				     ib_result_mc_address, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_cs_ctx_free(context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+}
diff --git a/tests/amdgpu/uvd_messages.h b/tests/amdgpu/decode_messages.h
similarity index 96%
rename from tests/amdgpu/uvd_messages.h
rename to tests/amdgpu/decode_messages.h
index 00235cb..bd6fe4b 100644
--- a/tests/amdgpu/uvd_messages.h
+++ b/tests/amdgpu/decode_messages.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Advanced Micro Devices, Inc.
+ * Copyright 2017 Advanced Micro Devices, Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -21,8 +21,10 @@
  *
  */
 
-#ifndef _UVD_MESSAGES_H_
-#define _UVD_MESSAGES_H_
+#ifndef _DECODE_MESSAGES_H_
+#define _DECODE_MESSAGES_H_
+
+#define SUM_DECODE 0x20345d8
 
 static const uint8_t uvd_create_msg[] = {
 	0xe4,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,
@@ -356,6 +358,9 @@
 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t avc_decode_msg[] = {
 	0x02,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x88,0x00,0x00,0x00,
 	0x01,0x00,0x00,0x01,0x00,0x03,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 	0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
@@ -810,4 +815,34 @@
 	0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
 };
 
-#endif /* _UVD_MESSAGES_H_ */
+static const uint8_t vcn_dec_create_msg[] = {
+	0x28,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00,
+	0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x60,0x03,0x00,0x00,0xe0,0x01,0x00,0x00,
+};
+
+static const uint8_t vcn_dec_decode_msg[] = {
+	0x28,0x00,0x00,0x00,0x90,0x06,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+	0x03,0x00,0x44,0x40,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x38,0x00,0x00,0x00,
+	0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0xec,0x00,0x00,0x00,
+	0x5c,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+	0x60,0x03,0x00,0x00,0xe0,0x01,0x00,0x00,0x80,0x05,0x00,0x00,0x00,0x94,0x6b,0x00,
+	0x96,0x4e,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x50,0x00,
+	0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,
+	0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x00,0x80,0x07,0x00,0x00,0x60,0x09,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t vcn_dec_destroy_msg[] = {
+	0x28,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+	0x03,0x00,0x44,0x40,0x00,0x00,0x00,0x00,
+};
+
+#endif /* _DECODE_MESSAGES_H_ */
diff --git a/tests/amdgpu/frame.h b/tests/amdgpu/frame.h
index 4c946c2..335401c 100644
--- a/tests/amdgpu/frame.h
+++ b/tests/amdgpu/frame.h
@@ -24,7 +24,7 @@
 #ifndef _frame_h_
 #define _frame_h_
 
-const uint8_t frame[] = {
+static const uint8_t frame[] = {
 	0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
 	0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2,
 	0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xaa, 0xaa, 0xaa,
diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build
new file mode 100644
index 0000000..4c1237c
--- /dev/null
+++ b/tests/amdgpu/meson.build
@@ -0,0 +1,34 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+if dep_cunit.found()
+  amdgpu_test = executable(
+    'amdgpu_test',
+    files(
+      'amdgpu_test.c', 'basic_tests.c', 'bo_tests.c', 'cs_tests.c',
+      'vce_tests.c', 'uvd_enc_tests.c', 'vcn_tests.c', 'deadlock_tests.c',
+      'vm_tests.c',
+    ),
+    dependencies : [dep_cunit, dep_threads],
+    include_directories : [inc_root, inc_drm, include_directories('../../amdgpu')],
+    link_with : [libdrm, libdrm_amdgpu],
+    install : with_install_tests,
+  )
+endif
diff --git a/tests/amdgpu/uvd_enc_tests.c b/tests/amdgpu/uvd_enc_tests.c
new file mode 100644
index 0000000..b4251bc
--- /dev/null
+++ b/tests/amdgpu/uvd_enc_tests.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+*/
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "CUnit/Basic.h"
+
+#include "util_math.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include "frame.h"
+#include "uve_ib.h"
+
+#define IB_SIZE		4096
+#define MAX_RESOURCES	16
+
+struct amdgpu_uvd_enc_bo {
+	amdgpu_bo_handle handle;
+	amdgpu_va_handle va_handle;
+	uint64_t addr;
+	uint64_t size;
+	uint8_t *ptr;
+};
+
+struct amdgpu_uvd_enc {
+	unsigned width;
+	unsigned height;
+	struct amdgpu_uvd_enc_bo session;
+	struct amdgpu_uvd_enc_bo vbuf;
+	struct amdgpu_uvd_enc_bo bs;
+	struct amdgpu_uvd_enc_bo fb;
+	struct amdgpu_uvd_enc_bo cpb;
+};
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static amdgpu_va_handle ib_va_handle;
+static uint64_t ib_mc_address;
+static uint32_t *ib_cpu;
+
+static struct amdgpu_uvd_enc enc;
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+
+static void amdgpu_cs_uvd_enc_create(void);
+static void amdgpu_cs_uvd_enc_session_init(void);
+static void amdgpu_cs_uvd_enc_encode(void);
+static void amdgpu_cs_uvd_enc_destroy(void);
+
+
+CU_TestInfo uvd_enc_tests[] = {
+	{ "UVD ENC create",  amdgpu_cs_uvd_enc_create },
+	{ "UVD ENC session init",  amdgpu_cs_uvd_enc_session_init },
+	{ "UVD ENC encode",  amdgpu_cs_uvd_enc_encode },
+	{ "UVD ENC destroy",  amdgpu_cs_uvd_enc_destroy },
+	CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_uvd_enc_tests_enable(void)
+{
+	int r;
+	struct drm_amdgpu_info_hw_ip info;
+
+	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+					     &minor_version, &device_handle))
+		return CU_FALSE;
+
+	r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_UVD_ENC, 0, &info);
+
+	if (amdgpu_device_deinitialize(device_handle))
+		return CU_FALSE;
+
+	if (!info.available_rings)
+		printf("\n\nThe ASIC NOT support UVD ENC, suite disabled.\n");
+
+	return (r == 0 && (info.available_rings ? CU_TRUE : CU_FALSE));
+}
+
+
+int suite_uvd_enc_tests_init(void)
+{
+	int r;
+
+	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+				     &minor_version, &device_handle);
+	if (r)
+		return CUE_SINIT_FAILED;
+
+	family_id = device_handle->info.family_id;
+
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+	if (r)
+		return CUE_SINIT_FAILED;
+
+	r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
+				    AMDGPU_GEM_DOMAIN_GTT, 0,
+				    &ib_handle, (void**)&ib_cpu,
+				    &ib_mc_address, &ib_va_handle);
+	if (r)
+		return CUE_SINIT_FAILED;
+
+	return CUE_SUCCESS;
+}
+
+int suite_uvd_enc_tests_clean(void)
+{
+	int r;
+
+	r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
+				     ib_mc_address, IB_SIZE);
+	if (r)
+		return CUE_SCLEAN_FAILED;
+
+	r = amdgpu_cs_ctx_free(context_handle);
+	if (r)
+		return CUE_SCLEAN_FAILED;
+
+	r = amdgpu_device_deinitialize(device_handle);
+	if (r)
+		return CUE_SCLEAN_FAILED;
+
+	return CUE_SUCCESS;
+}
+
+static int submit(unsigned ndw, unsigned ip)
+{
+	struct amdgpu_cs_request ibs_request = {0};
+	struct amdgpu_cs_ib_info ib_info = {0};
+	struct amdgpu_cs_fence fence_status = {0};
+	uint32_t expired;
+	int r;
+
+	ib_info.ib_mc_address = ib_mc_address;
+	ib_info.size = ndw;
+
+	ibs_request.ip_type = ip;
+
+	r = amdgpu_bo_list_create(device_handle, num_resources, resources,
+				  NULL, &ibs_request.resources);
+	if (r)
+		return r;
+
+	ibs_request.number_of_ibs = 1;
+	ibs_request.ibs = &ib_info;
+	ibs_request.fence_info.handle = NULL;
+
+	r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+	if (r)
+		return r;
+
+	r = amdgpu_bo_list_destroy(ibs_request.resources);
+	if (r)
+		return r;
+
+	fence_status.context = context_handle;
+	fence_status.ip_type = ip;
+	fence_status.fence = ibs_request.seq_no;
+
+	r = amdgpu_cs_query_fence_status(&fence_status,
+					 AMDGPU_TIMEOUT_INFINITE,
+					 0, &expired);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void alloc_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo,
+			unsigned size, unsigned domain)
+{
+	struct amdgpu_bo_alloc_request req = {0};
+	amdgpu_bo_handle buf_handle;
+	amdgpu_va_handle va_handle;
+	uint64_t va = 0;
+	int r;
+
+	req.alloc_size = ALIGN(size, 4096);
+	req.preferred_heap = domain;
+	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_va_range_alloc(device_handle,
+				  amdgpu_gpu_va_range_general,
+				  req.alloc_size, 1, 0, &va,
+				  &va_handle, 0);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
+			    AMDGPU_VA_OP_MAP);
+	CU_ASSERT_EQUAL(r, 0);
+	uvd_enc_bo->addr = va;
+	uvd_enc_bo->handle = buf_handle;
+	uvd_enc_bo->size = req.alloc_size;
+	uvd_enc_bo->va_handle = va_handle;
+	r = amdgpu_bo_cpu_map(uvd_enc_bo->handle, (void **)&uvd_enc_bo->ptr);
+	CU_ASSERT_EQUAL(r, 0);
+	memset(uvd_enc_bo->ptr, 0, size);
+	r = amdgpu_bo_cpu_unmap(uvd_enc_bo->handle);
+	CU_ASSERT_EQUAL(r, 0);
+}
+
+static void free_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo)
+{
+	int r;
+
+	r = amdgpu_bo_va_op(uvd_enc_bo->handle, 0, uvd_enc_bo->size,
+			    uvd_enc_bo->addr, 0, AMDGPU_VA_OP_UNMAP);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_va_range_free(uvd_enc_bo->va_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_free(uvd_enc_bo->handle);
+	CU_ASSERT_EQUAL(r, 0);
+	memset(uvd_enc_bo, 0, sizeof(*uvd_enc_bo));
+}
+
+static void amdgpu_cs_uvd_enc_create(void)
+{
+	enc.width = 160;
+	enc.height = 128;
+
+	num_resources  = 0;
+	alloc_resource(&enc.session, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT);
+	resources[num_resources++] = enc.session.handle;
+	resources[num_resources++] = ib_handle;
+}
+
+static void check_result(struct amdgpu_uvd_enc *enc)
+{
+	uint64_t sum;
+	uint32_t s = 175602;
+	uint32_t *ptr, size;
+	int j, r;
+
+	r = amdgpu_bo_cpu_map(enc->fb.handle, (void **)&enc->fb.ptr);
+	CU_ASSERT_EQUAL(r, 0);
+	ptr = (uint32_t *)enc->fb.ptr;
+	size = ptr[6];
+	r = amdgpu_bo_cpu_unmap(enc->fb.handle);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_bo_cpu_map(enc->bs.handle, (void **)&enc->bs.ptr);
+	CU_ASSERT_EQUAL(r, 0);
+	for (j = 0, sum = 0; j < size; ++j)
+		sum += enc->bs.ptr[j];
+	CU_ASSERT_EQUAL(sum, s);
+	r = amdgpu_bo_cpu_unmap(enc->bs.handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+}
+
+static void amdgpu_cs_uvd_enc_session_init(void)
+{
+	int len, r;
+
+	len = 0;
+	memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+	len += sizeof(uve_session_info) / 4;
+	ib_cpu[len++] = enc.session.addr >> 32;
+	ib_cpu[len++] = enc.session.addr;
+
+	memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+	len += sizeof(uve_task_info) / 4;
+	ib_cpu[len++] = 0x000000d8;
+	ib_cpu[len++] = 0x00000000;
+	ib_cpu[len++] = 0x00000000;
+
+	memcpy((ib_cpu + len), uve_op_init, sizeof(uve_op_init));
+	len += sizeof(uve_op_init) / 4;
+
+	memcpy((ib_cpu + len), uve_session_init, sizeof(uve_session_init));
+	len += sizeof(uve_session_init) / 4;
+
+	memcpy((ib_cpu + len), uve_layer_ctrl, sizeof(uve_layer_ctrl));
+	len += sizeof(uve_layer_ctrl) / 4;
+
+	memcpy((ib_cpu + len), uve_slice_ctrl, sizeof(uve_slice_ctrl));
+	len += sizeof(uve_slice_ctrl) / 4;
+
+	memcpy((ib_cpu + len), uve_spec_misc, sizeof(uve_spec_misc));
+	len += sizeof(uve_spec_misc) / 4;
+
+	memcpy((ib_cpu + len), uve_rc_session_init, sizeof(uve_rc_session_init));
+	len += sizeof(uve_rc_session_init) / 4;
+
+	memcpy((ib_cpu + len), uve_deblocking_filter, sizeof(uve_deblocking_filter));
+	len += sizeof(uve_deblocking_filter) / 4;
+
+	memcpy((ib_cpu + len), uve_quality_params, sizeof(uve_quality_params));
+	len += sizeof(uve_quality_params) / 4;
+
+	memcpy((ib_cpu + len), uve_op_init_rc, sizeof(uve_op_init_rc));
+	len += sizeof(uve_op_init_rc) / 4;
+
+	memcpy((ib_cpu + len), uve_op_init_rc_vbv_level, sizeof(uve_op_init_rc_vbv_level));
+	len += sizeof(uve_op_init_rc_vbv_level) / 4;
+
+	r = submit(len, AMDGPU_HW_IP_UVD_ENC);
+	CU_ASSERT_EQUAL(r, 0);
+}
+
+static void amdgpu_cs_uvd_enc_encode(void)
+{
+	int len, r, i;
+	uint64_t luma_offset, chroma_offset;
+	uint32_t vbuf_size, bs_size = 0x003f4800, cpb_size;
+	unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+	vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5;
+	cpb_size = vbuf_size * 10;
+
+
+	num_resources  = 0;
+	alloc_resource(&enc.fb, 4096, AMDGPU_GEM_DOMAIN_VRAM);
+	resources[num_resources++] = enc.fb.handle;
+	alloc_resource(&enc.bs, bs_size, AMDGPU_GEM_DOMAIN_VRAM);
+	resources[num_resources++] = enc.bs.handle;
+	alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM);
+	resources[num_resources++] = enc.vbuf.handle;
+	alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM);
+	resources[num_resources++] = enc.cpb.handle;
+	resources[num_resources++] = ib_handle;
+
+	r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr);
+	CU_ASSERT_EQUAL(r, 0);
+
+	memset(enc.vbuf.ptr, 0, vbuf_size);
+	for (i = 0; i < enc.height; ++i) {
+		memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width);
+		enc.vbuf.ptr += ALIGN(enc.width, align);
+	}
+	for (i = 0; i < enc.height / 2; ++i) {
+		memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width);
+		enc.vbuf.ptr += ALIGN(enc.width, align);
+	}
+
+	r = amdgpu_bo_cpu_unmap(enc.vbuf.handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	len = 0;
+	memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+	len += sizeof(uve_session_info) / 4;
+	ib_cpu[len++] = enc.session.addr >> 32;
+	ib_cpu[len++] = enc.session.addr;
+
+	memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+	len += sizeof(uve_task_info) / 4;
+	ib_cpu[len++] = 0x000005e0;
+	ib_cpu[len++] = 0x00000001;
+	ib_cpu[len++] = 0x00000001;
+
+	memcpy((ib_cpu + len), uve_nalu_buffer_1, sizeof(uve_nalu_buffer_1));
+	len += sizeof(uve_nalu_buffer_1) / 4;
+
+	memcpy((ib_cpu + len), uve_nalu_buffer_2, sizeof(uve_nalu_buffer_2));
+	len += sizeof(uve_nalu_buffer_2) / 4;
+
+	memcpy((ib_cpu + len), uve_nalu_buffer_3, sizeof(uve_nalu_buffer_3));
+	len += sizeof(uve_nalu_buffer_3) / 4;
+
+	memcpy((ib_cpu + len), uve_nalu_buffer_4, sizeof(uve_nalu_buffer_4));
+	len += sizeof(uve_nalu_buffer_4) / 4;
+
+	memcpy((ib_cpu + len), uve_slice_header, sizeof(uve_slice_header));
+	len += sizeof(uve_slice_header) / 4;
+
+	ib_cpu[len++] = 0x00000254;
+	ib_cpu[len++] = 0x00000010;
+	ib_cpu[len++] = enc.cpb.addr >> 32;
+	ib_cpu[len++] = enc.cpb.addr;
+	memcpy((ib_cpu + len), uve_ctx_buffer, sizeof(uve_ctx_buffer));
+	len += sizeof(uve_ctx_buffer) / 4;
+
+	memcpy((ib_cpu + len), uve_bitstream_buffer, sizeof(uve_bitstream_buffer));
+	len += sizeof(uve_bitstream_buffer) / 4;
+	ib_cpu[len++] = 0x00000000;
+	ib_cpu[len++] = enc.bs.addr >> 32;
+	ib_cpu[len++] = enc.bs.addr;
+	ib_cpu[len++] = 0x003f4800;
+	ib_cpu[len++] = 0x00000000;
+
+	memcpy((ib_cpu + len), uve_feedback_buffer, sizeof(uve_feedback_buffer));
+	len += sizeof(uve_feedback_buffer) / 4;
+	ib_cpu[len++] = enc.fb.addr >> 32;
+	ib_cpu[len++] = enc.fb.addr;
+	ib_cpu[len++] = 0x00000010;
+	ib_cpu[len++] = 0x00000028;
+
+	memcpy((ib_cpu + len), uve_feedback_buffer_additional, sizeof(uve_feedback_buffer_additional));
+	len += sizeof(uve_feedback_buffer_additional) / 4;
+
+	memcpy((ib_cpu + len), uve_intra_refresh, sizeof(uve_intra_refresh));
+	len += sizeof(uve_intra_refresh) / 4;
+
+	memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
+	len += sizeof(uve_layer_select) / 4;
+
+	memcpy((ib_cpu + len), uve_rc_layer_init, sizeof(uve_rc_layer_init));
+	len += sizeof(uve_rc_layer_init) / 4;
+
+	memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
+	len += sizeof(uve_layer_select) / 4;
+
+	memcpy((ib_cpu + len), uve_rc_per_pic, sizeof(uve_rc_per_pic));
+	len += sizeof(uve_rc_per_pic) / 4;
+
+	unsigned luma_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16);
+	luma_offset = enc.vbuf.addr;
+	chroma_offset = luma_offset + luma_size;
+	ib_cpu[len++] = 0x00000054;
+	ib_cpu[len++] = 0x0000000c;
+	ib_cpu[len++] = 0x00000002;
+	ib_cpu[len++] = 0x003f4800;
+	ib_cpu[len++] = luma_offset >> 32;
+	ib_cpu[len++] = luma_offset;
+	ib_cpu[len++] = chroma_offset >> 32;
+	ib_cpu[len++] = chroma_offset;
+	memcpy((ib_cpu + len), uve_encode_param, sizeof(uve_encode_param));
+	ib_cpu[len] = ALIGN(enc.width, align);
+	ib_cpu[len + 1] = ALIGN(enc.width, align);
+	len += sizeof(uve_encode_param) / 4;
+
+	memcpy((ib_cpu + len), uve_op_speed_enc_mode, sizeof(uve_op_speed_enc_mode));
+	len += sizeof(uve_op_speed_enc_mode) / 4;
+
+	memcpy((ib_cpu + len), uve_op_encode, sizeof(uve_op_encode));
+	len += sizeof(uve_op_encode) / 4;
+
+	r = submit(len, AMDGPU_HW_IP_UVD_ENC);
+	CU_ASSERT_EQUAL(r, 0);
+
+	check_result(&enc);
+
+	free_resource(&enc.fb);
+	free_resource(&enc.bs);
+	free_resource(&enc.vbuf);
+	free_resource(&enc.cpb);
+}
+
+static void amdgpu_cs_uvd_enc_destroy(void)
+{
+	int len, r;
+
+	num_resources  = 0;
+	resources[num_resources++] = ib_handle;
+
+	len = 0;
+	memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+	len += sizeof(uve_session_info) / 4;
+	ib_cpu[len++] = enc.session.addr >> 32;
+	ib_cpu[len++] = enc.session.addr;
+
+	memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+	len += sizeof(uve_task_info) / 4;
+	ib_cpu[len++] = 0xffffffff;
+	ib_cpu[len++] = 0x00000002;
+	ib_cpu[len++] = 0x00000000;
+
+	memcpy((ib_cpu + len), uve_op_close, sizeof(uve_op_close));
+	len += sizeof(uve_op_close) / 4;
+
+	r = submit(len, AMDGPU_HW_IP_UVD_ENC);
+	CU_ASSERT_EQUAL(r, 0);
+
+	free_resource(&enc.session);
+}
diff --git a/tests/amdgpu/uve_ib.h b/tests/amdgpu/uve_ib.h
new file mode 100644
index 0000000..cb72be2
--- /dev/null
+++ b/tests/amdgpu/uve_ib.h
@@ -0,0 +1,527 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+*/
+
+#ifndef _uve_ib_h_
+#define _uve_ib_h_
+
+static const uint32_t uve_session_info[] = {
+	0x00000018,
+	0x00000001,
+	0x00000000,
+	0x00010000,
+};
+
+static const uint32_t uve_task_info[] = {
+	0x00000014,
+	0x00000002,
+};
+
+static const uint32_t uve_session_init[] = {
+	0x00000020,
+	0x00000003,
+	0x000000c0,
+	0x00000080,
+	0x00000020,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const uint32_t uve_layer_ctrl[] = {
+	0x00000010,
+	0x00000004,
+	0x00000001,
+	0x00000001,
+};
+
+static const uint32_t uve_layer_select[] = {
+	0x0000000c,
+	0x00000005,
+	0x00000000,
+};
+
+static const uint32_t uve_slice_ctrl[] = {
+	0x00000014,
+	0x00000006,
+	0x00000000,
+	0x00000006,
+	0x00000006,
+};
+
+static const uint32_t uve_spec_misc[] = {
+	0x00000024,
+	0x00000007,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000001,
+	0x00000001,
+};
+
+static const uint32_t uve_rc_session_init[] = {
+	0x00000010,
+	0x00000008,
+	0x00000000,
+	0x00000040,
+};
+
+static const uint32_t uve_rc_layer_init[] = {
+	0x00000028,
+	0x00000009,
+	0x001e8480,
+	0x001e8480,
+	0x0000001e,
+	0x00000001,
+	0x0001046a,
+	0x0001046a,
+	0x0001046a,
+	0xaaaaaaaa,
+};
+
+static const uint32_t uve_deblocking_filter[] = {
+	0x00000020,
+	0x0000000e,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const uint32_t uve_quality_params[] = {
+	0x00000014,
+	0x0000000d,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const uint32_t uve_feedback_buffer[] = {
+	0x0000001c,
+	0x00000012,
+	0x00000000,
+};
+
+static const uint32_t uve_feedback_buffer_additional[] = {
+	0x00000108,
+	0x00000014,
+	0x00000001,
+	0x00000010,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const uint32_t uve_nalu_buffer_1[] = {
+	0x00000018,
+	0x00000013,
+	0x00000001,
+	0x00000007,
+	0x00000001,
+	0x46011000,
+};
+
+static const uint32_t uve_nalu_buffer_2[] = {
+	0x0000002c,
+	0x00000013,
+	0x00000002,
+	0x0000001b,
+	0x00000001,
+	0x40010c01,
+	0xffff0160,
+	0x00000300,
+	0xb0000003,
+	0x00000300,
+	0x962c0900,
+};
+
+static const uint32_t uve_nalu_buffer_3[] = {
+	0x00000034,
+	0x00000013,
+	0x00000003,
+	0x00000023,
+	0x00000001,
+	0x42010101,
+	0x60000003,
+	0x00b00000,
+	0x03000003,
+	0x0096a018,
+	0x2020708f,
+	0xcb924295,
+	0x12e08000,
+};
+
+static const uint32_t uve_nalu_buffer_4[] = {
+	0x0000001c,
+	0x00000013,
+	0x00000004,
+	0x0000000b,
+	0x00000001,
+	0x4401e0f1,
+	0x80992000,
+};
+
+static const uint32_t uve_slice_header[] = {
+	0x000000c8,
+	0x0000000b,
+	0x28010000,
+	0x40000000,
+	0x60000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000002,
+	0x00000010,
+	0x00000003,
+	0x00000000,
+	0x00000002,
+	0x00000002,
+	0x00000004,
+	0x00000000,
+	0x00000001,
+	0x00000000,
+	0x00000002,
+	0x00000003,
+	0x00000005,
+	0x00000000,
+	0x00000002,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const uint32_t uve_encode_param[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0xffffffff,
+	0x00000001,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const uint32_t uve_intra_refresh[] = {
+	0x00000014,
+	0x0000000f,
+	0x00000000,
+	0x00000000,
+	0x00000001,
+};
+
+static const uint32_t uve_ctx_buffer[] = {
+	0x00000000,
+	0x00000000,
+	0x000000a0,
+	0x000000a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const uint32_t uve_bitstream_buffer[] = {
+	0x0000001c,
+	0x00000011,
+};
+
+static const uint32_t uve_rc_per_pic[] = {
+	0x00000024,
+	0x0000000a,
+	0x0000001a,
+	0x00000000,
+	0x00000033,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000001,
+};
+
+static const uint32_t uve_op_init[] = {
+	0x00000008,
+	0x08000001,
+};
+
+static const uint32_t uve_op_close[] = {
+	0x00000008,
+	0x08000002,
+};
+
+static const uint32_t uve_op_encode[] = {
+	0x00000008,
+	0x08000003,
+};
+
+static const uint32_t uve_op_init_rc[] = {
+	0x00000008,
+	0x08000004,
+};
+
+static const uint32_t uve_op_init_rc_vbv_level[] = {
+	0x00000008,
+	0x08000005,
+};
+
+static const uint32_t uve_op_speed_enc_mode[] = {
+	0x00000008,
+	0x08000006,
+};
+
+static const uint32_t uve_op_balance_enc_mode[] = {
+	0x00000008,
+	0x08000007,
+};
+
+static const uint32_t uve_op_quality_enc_mode[] = {
+	0x00000008,
+	0x08000008,
+};
+#endif /*_uve_ib_h*/
diff --git a/tests/amdgpu/vce_tests.c b/tests/amdgpu/vce_tests.c
index de63aa1..25c0b1f 100644
--- a/tests/amdgpu/vce_tests.c
+++ b/tests/amdgpu/vce_tests.c
@@ -21,10 +21,6 @@
  *
 */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdio.h>
 #include <inttypes.h>
 
@@ -88,6 +84,27 @@
 	CU_TEST_INFO_NULL,
 };
 
+
+CU_BOOL suite_vce_tests_enable(void)
+{
+	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+					     &minor_version, &device_handle))
+		return CU_FALSE;
+
+	family_id = device_handle->info.family_id;
+
+	if (amdgpu_device_deinitialize(device_handle))
+		return CU_FALSE;
+
+
+	if (family_id >= AMDGPU_FAMILY_RV || family_id == AMDGPU_FAMILY_SI) {
+		printf("\n\nThe ASIC NOT support VCE, suite disabled\n");
+		return CU_FALSE;
+	}
+
+	return CU_TRUE;
+}
+
 int suite_vce_tests_init(void)
 {
 	int r;
@@ -234,6 +251,7 @@
 
 static void amdgpu_cs_vce_create(void)
 {
+	unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
 	int len, r;
 
 	enc.width = vce_create[6];
@@ -250,6 +268,8 @@
 	memcpy((ib_cpu + len), vce_taskinfo, sizeof(vce_taskinfo));
 	len += sizeof(vce_taskinfo) / 4;
 	memcpy((ib_cpu + len), vce_create, sizeof(vce_create));
+	ib_cpu[len + 8] = ALIGN(enc.width, align);
+	ib_cpu[len + 9] = ALIGN(enc.width, align);
 	len += sizeof(vce_create) / 4;
 	memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
 	ib_cpu[len + 2] = enc.fb[0].addr >> 32;
@@ -291,10 +311,12 @@
 {
 
 	uint64_t luma_offset, chroma_offset;
-	int len = 0, r;
+	unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+	unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16);
+	int len = 0, i, r;
 
 	luma_offset = enc->vbuf.addr;
-	chroma_offset = luma_offset + enc->width * enc->height;
+	chroma_offset = luma_offset + luma_size;
 
 	memcpy((ib_cpu + len), vce_session, sizeof(vce_session));
 	len += sizeof(vce_session) / 4;
@@ -309,6 +331,10 @@
 	ib_cpu[len + 3] = enc->cpb.addr;
 	len += sizeof(vce_context_buffer) / 4;
 	memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer));
+	for (i = 0; i <  8; ++i)
+		ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2);
+	for (i = 0; i <  8; ++i)
+		ib_cpu[len + 10 + i] = luma_size * 1.5;
 	len += sizeof(vce_aux_buffer) / 4;
 	memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
 	ib_cpu[len + 2] = enc->fb[0].addr >> 32;
@@ -319,8 +345,10 @@
 	ib_cpu[len + 10] = luma_offset;
 	ib_cpu[len + 11] = chroma_offset >> 32;
 	ib_cpu[len + 12] = chroma_offset;
-	ib_cpu[len + 73] = 0x7800;
-	ib_cpu[len + 74] = 0x7800 + 0x5000;
+	ib_cpu[len + 14] = ALIGN(enc->width, align);
+	ib_cpu[len + 15] = ALIGN(enc->width, align);
+	ib_cpu[len + 73] = luma_size * 1.5;
+	ib_cpu[len + 74] = luma_size * 2.5;
 	len += sizeof(vce_encode) / 4;
 	enc->ib_len = len;
 	if (!enc->two_instance) {
@@ -332,11 +360,13 @@
 static void amdgpu_cs_vce_encode_p(struct amdgpu_vce_encode *enc)
 {
 	uint64_t luma_offset, chroma_offset;
-	int len, r;
+	int len, i, r;
+	unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+	unsigned luma_size = ALIGN(enc->width, align) * ALIGN(enc->height, 16);
 
 	len = (enc->two_instance) ? enc->ib_len : 0;
 	luma_offset = enc->vbuf.addr;
-	chroma_offset = luma_offset + enc->width * enc->height;
+	chroma_offset = luma_offset + luma_size;
 
 	if (!enc->two_instance) {
 		memcpy((ib_cpu + len), vce_session, sizeof(vce_session));
@@ -353,6 +383,10 @@
 	ib_cpu[len + 3] = enc->cpb.addr;
 	len += sizeof(vce_context_buffer) / 4;
 	memcpy((ib_cpu + len), vce_aux_buffer, sizeof(vce_aux_buffer));
+	for (i = 0; i <  8; ++i)
+		ib_cpu[len + 2 + i] = luma_size * 1.5 * (i + 2);
+	for (i = 0; i <  8; ++i)
+		ib_cpu[len + 10 + i] = luma_size * 1.5;
 	len += sizeof(vce_aux_buffer) / 4;
 	memcpy((ib_cpu + len), vce_feedback, sizeof(vce_feedback));
 	ib_cpu[len + 2] = enc->fb[1].addr >> 32;
@@ -364,15 +398,17 @@
 	ib_cpu[len + 10] = luma_offset;
 	ib_cpu[len + 11] = chroma_offset >> 32;
 	ib_cpu[len + 12] = chroma_offset;
+	ib_cpu[len + 14] = ALIGN(enc->width, align);
+	ib_cpu[len + 15] = ALIGN(enc->width, align);
 	ib_cpu[len + 18] = 0;
 	ib_cpu[len + 19] = 0;
 	ib_cpu[len + 56] = 3;
 	ib_cpu[len + 57] = 0;
 	ib_cpu[len + 58] = 0;
-	ib_cpu[len + 59] = 0x7800;
-	ib_cpu[len + 60] = 0x7800 + 0x5000;
+	ib_cpu[len + 59] = luma_size * 1.5;
+	ib_cpu[len + 60] = luma_size * 2.5;
 	ib_cpu[len + 73] = 0;
-	ib_cpu[len + 74] = 0x5000;
+	ib_cpu[len + 74] = luma_size;
 	ib_cpu[len + 81] = 1;
 	ib_cpu[len + 82] = 1;
 	len += sizeof(vce_encode) / 4;
@@ -408,9 +444,10 @@
 static void amdgpu_cs_vce_encode(void)
 {
 	uint32_t vbuf_size, bs_size = 0x154000, cpb_size;
-	int r;
+	unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+	int i, r;
 
-	vbuf_size = enc.width * enc.height * 1.5;
+	vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5;
 	cpb_size = vbuf_size * 10;
 	num_resources = 0;
 	alloc_resource(&enc.fb[0], 4096, AMDGPU_GEM_DOMAIN_GTT);
@@ -429,7 +466,17 @@
 
 	r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr);
 	CU_ASSERT_EQUAL(r, 0);
-	memcpy(enc.vbuf.ptr, frame, sizeof(frame));
+
+	memset(enc.vbuf.ptr, 0, vbuf_size);
+	for (i = 0; i < enc.height; ++i) {
+		memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width);
+		enc.vbuf.ptr += ALIGN(enc.width, align);
+	}
+	for (i = 0; i < enc.height / 2; ++i) {
+		memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width);
+		enc.vbuf.ptr += ALIGN(enc.width, align);
+	}
+
 	r = amdgpu_bo_cpu_unmap(enc.vbuf.handle);
 	CU_ASSERT_EQUAL(r, 0);
 
diff --git a/tests/amdgpu/vcn_tests.c b/tests/amdgpu/vcn_tests.c
new file mode 100644
index 0000000..d9f05af
--- /dev/null
+++ b/tests/amdgpu/vcn_tests.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+*/
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "CUnit/Basic.h"
+
+#include "util_math.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+#include "decode_messages.h"
+
+#define IB_SIZE		4096
+#define MAX_RESOURCES	16
+
+struct amdgpu_vcn_bo {
+	amdgpu_bo_handle handle;
+	amdgpu_va_handle va_handle;
+	uint64_t addr;
+	uint64_t size;
+	uint8_t *ptr;
+};
+
+static amdgpu_device_handle device_handle;
+static uint32_t major_version;
+static uint32_t minor_version;
+static uint32_t family_id;
+
+static amdgpu_context_handle context_handle;
+static amdgpu_bo_handle ib_handle;
+static amdgpu_va_handle ib_va_handle;
+static uint64_t ib_mc_address;
+static uint32_t *ib_cpu;
+
+static amdgpu_bo_handle resources[MAX_RESOURCES];
+static unsigned num_resources;
+
+static void amdgpu_cs_vcn_dec_create(void);
+static void amdgpu_cs_vcn_dec_decode(void);
+static void amdgpu_cs_vcn_dec_destroy(void);
+
+static void amdgpu_cs_vcn_enc_create(void);
+static void amdgpu_cs_vcn_enc_encode(void);
+static void amdgpu_cs_vcn_enc_destroy(void);
+
+CU_TestInfo vcn_tests[] = {
+
+	{ "VCN DEC create",  amdgpu_cs_vcn_dec_create },
+	{ "VCN DEC decode",  amdgpu_cs_vcn_dec_decode },
+	{ "VCN DEC destroy",  amdgpu_cs_vcn_dec_destroy },
+
+	{ "VCN ENC create",  amdgpu_cs_vcn_enc_create },
+	{ "VCN ENC decode",  amdgpu_cs_vcn_enc_encode },
+	{ "VCN ENC destroy",  amdgpu_cs_vcn_enc_destroy },
+	CU_TEST_INFO_NULL,
+};
+
+CU_BOOL suite_vcn_tests_enable(void)
+{
+
+	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+				   &minor_version, &device_handle))
+		return CU_FALSE;
+
+	family_id = device_handle->info.family_id;
+
+	if (amdgpu_device_deinitialize(device_handle))
+			return CU_FALSE;
+
+
+	if (family_id < AMDGPU_FAMILY_RV) {
+		printf("\n\nThe ASIC NOT support VCN, suite disabled\n");
+		return CU_FALSE;
+	}
+
+	return CU_TRUE;
+}
+
+int suite_vcn_tests_init(void)
+{
+	int r;
+
+	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+				     &minor_version, &device_handle);
+	if (r)
+		return CUE_SINIT_FAILED;
+
+	family_id = device_handle->info.family_id;
+
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+	if (r)
+		return CUE_SINIT_FAILED;
+
+	r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
+				    AMDGPU_GEM_DOMAIN_GTT, 0,
+				    &ib_handle, (void**)&ib_cpu,
+				    &ib_mc_address, &ib_va_handle);
+	if (r)
+		return CUE_SINIT_FAILED;
+
+	return CUE_SUCCESS;
+}
+
+int suite_vcn_tests_clean(void)
+{
+	int r;
+
+	r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
+			     ib_mc_address, IB_SIZE);
+	if (r)
+		return CUE_SCLEAN_FAILED;
+
+	r = amdgpu_cs_ctx_free(context_handle);
+	if (r)
+		return CUE_SCLEAN_FAILED;
+
+	r = amdgpu_device_deinitialize(device_handle);
+	if (r)
+		return CUE_SCLEAN_FAILED;
+
+	return CUE_SUCCESS;
+}
+
+static int submit(unsigned ndw, unsigned ip)
+{
+	struct amdgpu_cs_request ibs_request = {0};
+	struct amdgpu_cs_ib_info ib_info = {0};
+	struct amdgpu_cs_fence fence_status = {0};
+	uint32_t expired;
+	int r;
+
+	ib_info.ib_mc_address = ib_mc_address;
+	ib_info.size = ndw;
+
+	ibs_request.ip_type = ip;
+
+	r = amdgpu_bo_list_create(device_handle, num_resources, resources,
+				  NULL, &ibs_request.resources);
+	if (r)
+		return r;
+
+	ibs_request.number_of_ibs = 1;
+	ibs_request.ibs = &ib_info;
+	ibs_request.fence_info.handle = NULL;
+
+	r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
+	if (r)
+		return r;
+
+	r = amdgpu_bo_list_destroy(ibs_request.resources);
+	if (r)
+		return r;
+
+	fence_status.context = context_handle;
+	fence_status.ip_type = ip;
+	fence_status.fence = ibs_request.seq_no;
+
+	r = amdgpu_cs_query_fence_status(&fence_status,
+					 AMDGPU_TIMEOUT_INFINITE,
+					 0, &expired);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void alloc_resource(struct amdgpu_vcn_bo *vcn_bo,
+			unsigned size, unsigned domain)
+{
+	struct amdgpu_bo_alloc_request req = {0};
+	amdgpu_bo_handle buf_handle;
+	amdgpu_va_handle va_handle;
+	uint64_t va = 0;
+	int r;
+
+	req.alloc_size = ALIGN(size, 4096);
+	req.preferred_heap = domain;
+	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_va_range_alloc(device_handle,
+				  amdgpu_gpu_va_range_general,
+				  req.alloc_size, 1, 0, &va,
+				  &va_handle, 0);
+	CU_ASSERT_EQUAL(r, 0);
+	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
+			    AMDGPU_VA_OP_MAP);
+	CU_ASSERT_EQUAL(r, 0);
+	vcn_bo->addr = va;
+	vcn_bo->handle = buf_handle;
+	vcn_bo->size = req.alloc_size;
+	vcn_bo->va_handle = va_handle;
+	r = amdgpu_bo_cpu_map(vcn_bo->handle, (void **)&vcn_bo->ptr);
+	CU_ASSERT_EQUAL(r, 0);
+	memset(vcn_bo->ptr, 0, size);
+	r = amdgpu_bo_cpu_unmap(vcn_bo->handle);
+	CU_ASSERT_EQUAL(r, 0);
+}
+
+static void free_resource(struct amdgpu_vcn_bo *vcn_bo)
+{
+	int r;
+
+	r = amdgpu_bo_va_op(vcn_bo->handle, 0, vcn_bo->size,
+			    vcn_bo->addr, 0, AMDGPU_VA_OP_UNMAP);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_va_range_free(vcn_bo->va_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_free(vcn_bo->handle);
+	CU_ASSERT_EQUAL(r, 0);
+	memset(vcn_bo, 0, sizeof(*vcn_bo));
+}
+
+static void vcn_dec_cmd(uint64_t addr, unsigned cmd, int *idx)
+{
+	ib_cpu[(*idx)++] = 0x81C4;
+	ib_cpu[(*idx)++] = addr;
+	ib_cpu[(*idx)++] = 0x81C5;
+	ib_cpu[(*idx)++] = addr >> 32;
+	ib_cpu[(*idx)++] = 0x81C3;
+	ib_cpu[(*idx)++] = cmd << 1;
+}
+
+static void amdgpu_cs_vcn_dec_create(void)
+{
+	struct amdgpu_vcn_bo msg_buf;
+	int len, r;
+
+	num_resources  = 0;
+	alloc_resource(&msg_buf, 4096, AMDGPU_GEM_DOMAIN_GTT);
+	resources[num_resources++] = msg_buf.handle;
+	resources[num_resources++] = ib_handle;
+
+	r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr);
+	CU_ASSERT_EQUAL(r, 0);
+
+	memset(msg_buf.ptr, 0, 4096);
+	memcpy(msg_buf.ptr, vcn_dec_create_msg, sizeof(vcn_dec_create_msg));
+
+	len = 0;
+	ib_cpu[len++] = 0x81C4;
+	ib_cpu[len++] = msg_buf.addr;
+	ib_cpu[len++] = 0x81C5;
+	ib_cpu[len++] = msg_buf.addr >> 32;
+	ib_cpu[len++] = 0x81C3;
+	ib_cpu[len++] = 0;
+	for (; len % 16; ++len)
+		ib_cpu[len] = 0x81ff;
+
+	r = submit(len, AMDGPU_HW_IP_VCN_DEC);
+	CU_ASSERT_EQUAL(r, 0);
+
+	free_resource(&msg_buf);
+}
+
+static void amdgpu_cs_vcn_dec_decode(void)
+{
+	const unsigned dpb_size = 15923584, dt_size = 737280;
+	uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, ctx_addr, dt_addr, it_addr, sum;
+	struct amdgpu_vcn_bo dec_buf;
+	int size, len, i, r;
+	uint8_t *dec;
+
+	size = 4*1024; /* msg */
+	size += 4*1024; /* fb */
+	size += 4096; /*it_scaling_table*/
+	size += ALIGN(sizeof(uvd_bitstream), 4*1024);
+	size += ALIGN(dpb_size, 4*1024);
+	size += ALIGN(dt_size, 4*1024);
+
+	num_resources  = 0;
+	alloc_resource(&dec_buf, size, AMDGPU_GEM_DOMAIN_GTT);
+	resources[num_resources++] = dec_buf.handle;
+	resources[num_resources++] = ib_handle;
+
+	r = amdgpu_bo_cpu_map(dec_buf.handle, (void **)&dec_buf.ptr);
+	dec = dec_buf.ptr;
+
+	CU_ASSERT_EQUAL(r, 0);
+	memset(dec_buf.ptr, 0, size);
+	memcpy(dec_buf.ptr, vcn_dec_decode_msg, sizeof(vcn_dec_decode_msg));
+	memcpy(dec_buf.ptr + sizeof(vcn_dec_decode_msg),
+			avc_decode_msg, sizeof(avc_decode_msg));
+
+	dec += 4*1024;
+	dec += 4*1024;
+	memcpy(dec, uvd_it_scaling_table, sizeof(uvd_it_scaling_table));
+
+	dec += 4*1024;
+	memcpy(dec, uvd_bitstream, sizeof(uvd_bitstream));
+
+	dec += ALIGN(sizeof(uvd_bitstream), 4*1024);
+
+	dec += ALIGN(dpb_size, 4*1024);
+
+	msg_addr = dec_buf.addr;
+	fb_addr = msg_addr + 4*1024;
+	it_addr = fb_addr + 4*1024;
+	bs_addr = it_addr + 4*1024;
+	dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024);
+	ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024);
+	dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024);
+
+	len = 0;
+	vcn_dec_cmd(msg_addr, 0x0, &len);
+	vcn_dec_cmd(dpb_addr, 0x1, &len);
+	vcn_dec_cmd(dt_addr, 0x2, &len);
+	vcn_dec_cmd(fb_addr, 0x3, &len);
+	vcn_dec_cmd(bs_addr, 0x100, &len);
+	vcn_dec_cmd(it_addr, 0x204, &len);
+	vcn_dec_cmd(ctx_addr, 0x206, &len);
+
+	ib_cpu[len++] = 0x81C6;
+	ib_cpu[len++] = 0x1;
+	for (; len % 16; ++len)
+		ib_cpu[len] = 0x80000000;
+
+	r = submit(len, AMDGPU_HW_IP_VCN_DEC);
+	CU_ASSERT_EQUAL(r, 0);
+
+	for (i = 0, sum = 0; i < dt_size; ++i)
+		sum += dec[i];
+
+	CU_ASSERT_EQUAL(sum, SUM_DECODE);
+
+	free_resource(&dec_buf);
+}
+
+static void amdgpu_cs_vcn_dec_destroy(void)
+{
+	struct amdgpu_vcn_bo msg_buf;
+	int len, r;
+
+	num_resources  = 0;
+	alloc_resource(&msg_buf, 1024, AMDGPU_GEM_DOMAIN_GTT);
+	resources[num_resources++] = msg_buf.handle;
+	resources[num_resources++] = ib_handle;
+
+	r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr);
+	CU_ASSERT_EQUAL(r, 0);
+
+	memset(msg_buf.ptr, 0, 1024);
+	memcpy(msg_buf.ptr, vcn_dec_destroy_msg, sizeof(vcn_dec_destroy_msg));
+
+	len = 0;
+	ib_cpu[len++] = 0x81C4;
+	ib_cpu[len++] = msg_buf.addr;
+	ib_cpu[len++] = 0x81C5;
+	ib_cpu[len++] = msg_buf.addr >> 32;
+	ib_cpu[len++] = 0x81C3;
+	ib_cpu[len++] = 0;
+	for (; len % 16; ++len)
+		ib_cpu[len] = 0x80000000;
+
+	r = submit(len, AMDGPU_HW_IP_VCN_DEC);
+	CU_ASSERT_EQUAL(r, 0);
+
+	free_resource(&msg_buf);
+}
+
+static void amdgpu_cs_vcn_enc_create(void)
+{
+	/* TODO */
+}
+
+static void amdgpu_cs_vcn_enc_encode(void)
+{
+	/* TODO */
+}
+
+static void amdgpu_cs_vcn_enc_destroy(void)
+{
+	/* TODO */
+}
diff --git a/tests/amdgpu/vm_tests.c b/tests/amdgpu/vm_tests.c
new file mode 100644
index 0000000..7b6dc5d
--- /dev/null
+++ b/tests/amdgpu/vm_tests.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+*/
+
+#include "CUnit/Basic.h"
+
+#include "amdgpu_test.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+static  amdgpu_device_handle device_handle;
+static  uint32_t  major_version;
+static  uint32_t  minor_version;
+
+
+static void amdgpu_vmid_reserve_test(void);
+
+CU_BOOL suite_vm_tests_enable(void)
+{
+    CU_BOOL enable = CU_TRUE;
+
+	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+				     &minor_version, &device_handle))
+		return CU_FALSE;
+
+	if (device_handle->info.family_id == AMDGPU_FAMILY_SI) {
+		printf("\n\nCurrently hangs the CP on this ASIC, VM suite disabled\n");
+		enable = CU_FALSE;
+	}
+
+	if (amdgpu_device_deinitialize(device_handle))
+		return CU_FALSE;
+
+	return enable;
+}
+
+int suite_vm_tests_init(void)
+{
+	int r;
+
+	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
+				   &minor_version, &device_handle);
+
+	if (r) {
+		if ((r == -EACCES) && (errno == EACCES))
+			printf("\n\nError:%s. "
+				"Hint:Try to run this test program as root.",
+				strerror(errno));
+		return CUE_SINIT_FAILED;
+	}
+
+	return CUE_SUCCESS;
+}
+
+int suite_vm_tests_clean(void)
+{
+	int r = amdgpu_device_deinitialize(device_handle);
+
+	if (r == 0)
+		return CUE_SUCCESS;
+	else
+		return CUE_SCLEAN_FAILED;
+}
+
+
+CU_TestInfo vm_tests[] = {
+	{ "resere vmid test",  amdgpu_vmid_reserve_test },
+	CU_TEST_INFO_NULL,
+};
+
+static void amdgpu_vmid_reserve_test(void)
+{
+	amdgpu_context_handle context_handle;
+	amdgpu_bo_handle ib_result_handle;
+	void *ib_result_cpu;
+	uint64_t ib_result_mc_address;
+	struct amdgpu_cs_request ibs_request;
+	struct amdgpu_cs_ib_info ib_info;
+	struct amdgpu_cs_fence fence_status;
+	uint32_t expired, flags;
+	int i, r;
+	amdgpu_bo_list_handle bo_list;
+	amdgpu_va_handle va_handle;
+	static uint32_t *ptr;
+
+	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	flags = 0;
+	r = amdgpu_vm_reserve_vmid(device_handle, flags);
+	CU_ASSERT_EQUAL(r, 0);
+
+
+	r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
+			AMDGPU_GEM_DOMAIN_GTT, 0,
+						    &ib_result_handle, &ib_result_cpu,
+						    &ib_result_mc_address, &va_handle);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
+			       &bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	ptr = ib_result_cpu;
+
+	for (i = 0; i < 16; ++i)
+		ptr[i] = 0xffff1000;
+
+	memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info));
+	ib_info.ib_mc_address = ib_result_mc_address;
+	ib_info.size = 16;
+
+	memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request));
+	ibs_request.ip_type = AMDGPU_HW_IP_GFX;
+	ibs_request.ring = 0;
+	ibs_request.number_of_ibs = 1;
+	ibs_request.ibs = &ib_info;
+	ibs_request.resources = bo_list;
+	ibs_request.fence_info.handle = NULL;
+
+	r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1);
+	CU_ASSERT_EQUAL(r, 0);
+
+
+	memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
+	fence_status.context = context_handle;
+	fence_status.ip_type = AMDGPU_HW_IP_GFX;
+	fence_status.ip_instance = 0;
+	fence_status.ring = 0;
+	fence_status.fence = ibs_request.seq_no;
+
+	r = amdgpu_cs_query_fence_status(&fence_status,
+			AMDGPU_TIMEOUT_INFINITE,0, &expired);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_list_destroy(bo_list);
+	CU_ASSERT_EQUAL(r, 0);
+
+	r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
+				     ib_result_mc_address, 4096);
+	CU_ASSERT_EQUAL(r, 0);
+
+	flags = 0;
+	r = amdgpu_vm_unreserve_vmid(device_handle, flags);
+	CU_ASSERT_EQUAL(r, 0);
+
+
+	r = amdgpu_cs_ctx_free(context_handle);
+	CU_ASSERT_EQUAL(r, 0);
+}
diff --git a/tests/drmsl.c b/tests/drmsl.c
index d0ac0ef..d1b59a8 100644
--- a/tests/drmsl.c
+++ b/tests/drmsl.c
@@ -106,7 +106,9 @@
     return usec;
 }
 
-static void print_neighbors(void *list, unsigned long key)
+static void print_neighbors(void *list, unsigned long key,
+                            unsigned long expected_prev,
+                            unsigned long expected_next)
 {
     unsigned long prev_key = 0;
     unsigned long next_key = 0;
@@ -119,6 +121,16 @@
 				  &next_key, &next_value);
     printf("Neighbors of %5lu: %d %5lu %5lu\n",
 	   key, retval, prev_key, next_key);
+    if (prev_key != expected_prev) {
+        fprintf(stderr, "Unexpected neighbor: %5lu. Expected: %5lu\n",
+                prev_key, expected_prev);
+	exit(1);
+    }
+    if (next_key != expected_next) {
+        fprintf(stderr, "Unexpected neighbor: %5lu. Expected: %5lu\n",
+                next_key, expected_next);
+	exit(1);
+    }
 }
 
 int main(void)
@@ -138,13 +150,13 @@
     print(list);
     printf("\n==============================\n\n");
 
-    print_neighbors(list, 0);
-    print_neighbors(list, 50);
-    print_neighbors(list, 51);
-    print_neighbors(list, 123);
-    print_neighbors(list, 200);
-    print_neighbors(list, 213);
-    print_neighbors(list, 256);
+    print_neighbors(list, 0, 0, 50);
+    print_neighbors(list, 50, 0, 50);
+    print_neighbors(list, 51, 50, 123);
+    print_neighbors(list, 123, 50, 123);
+    print_neighbors(list, 200, 123, 213);
+    print_neighbors(list, 213, 123, 213);
+    print_neighbors(list, 256, 213, 256);
     printf("\n==============================\n\n");
 
     drmSLDelete(list, 50);
diff --git a/tests/drmstat.c b/tests/drmstat.c
deleted file mode 100644
index 023aa06..0000000
--- a/tests/drmstat.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/* drmstat.c -- DRM device status and testing program
- * Created: Tue Jan  5 08:19:24 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * 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
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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: Rickard E. (Rik) Faith <faith@valinux.com>
- * 
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <getopt.h>
-#include <strings.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-#endif
-#include "xf86drm.h"
-
-int sigio_fd;
-
-static double usec(struct timeval *end, struct timeval *start)
-{
-    double e = end->tv_sec   * 1000000 + end->tv_usec;
-    double s = start->tv_sec * 1000000 + start->tv_usec;
-
-    return e - s;
-}
-
-static void getversion(int fd)
-{
-    drmVersionPtr version;
-    
-    version = drmGetVersion(fd);
-    if (version) {
-	printf( "Name: %s\n", version->name ? version->name : "?" );
-	printf( "    Version: %d.%d.%d\n",
-		version->version_major,
-		version->version_minor,
-		version->version_patchlevel );
-	printf( "    Date: %s\n", version->date ? version->date : "?" );
-	printf( "    Desc: %s\n", version->desc ? version->desc : "?" );
-	drmFreeVersion(version);
-    } else {
-	printf( "No driver available\n" );
-    }
-}
-
-static void process_sigio(char *device)
-{
-    int              fd;
-
-    if ((fd = open(device, 0)) < 0) {
-	drmError(-errno, __func__);
-	exit(1);
-    }
-
-    sigio_fd = fd;
-    for (;;) sleep(60);
-}
-
-int main(int argc, char **argv)
-{
-    int            c;
-    int            r  = 0;
-    int            fd = -1;
-    drm_handle_t      handle;
-    void           *address;
-    char           *pt;
-    unsigned long  count;
-    unsigned long  offset;
-    unsigned long  size;
-    drm_context_t  context;
-    int            loops;
-    char           buf[1024];
-    int            i;
-    drmBufInfoPtr  info;
-    drmBufMapPtr   bufs;
-    drmLockPtr     lock;
-    int            secs;
-
-    while ((c = getopt(argc, argv,
-		       "lc:vo:O:f:s:w:W:b:r:R:P:L:C:XS:B:F:")) != EOF)
-	switch (c) {
-	case 'F':
-	    count  = strtoul(optarg, NULL, 0);
-	    if (!fork()) {
-		dup(fd);
-		sleep(count);
-	    }
-	    close(fd);
-	    break;
-	case 'v': getversion(fd);                                        break;
-	case 'X':
-	    if ((r = drmCreateContext(fd, &context))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    printf( "Got %d\n", context);
-	    break;
-	case 'S':
-	    process_sigio(optarg);
-	    break;
-	case 'C':
-	    if ((r = drmSwitchToContext(fd, strtoul(optarg, NULL, 0)))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    break;
-	case 'c':
-	    if ((r = drmSetBusid(fd,optarg))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    break;
-	case 'o':
-	    if ((fd = drmOpen(optarg, NULL)) < 0) {
-		drmError(fd, argv[0]);
-		return 1;
-	    }
-	    break;
-	case 'O':
-	    if ((fd = drmOpen(NULL, optarg)) < 0) {
-		drmError(fd, argv[0]);
-		return 1;
-	    }
-	    break;
-	case 'B':		/* Test buffer allocation */
-	    count  = strtoul(optarg, &pt, 0);
-	    size   = strtoul(pt+1, &pt, 0);
-	    secs   = strtoul(pt+1, NULL, 0);
-	    {
-		drmDMAReq      dma;
-		int            *indices, *sizes;
-
-		indices = alloca(sizeof(*indices) * count);
-		sizes   = alloca(sizeof(*sizes)   * count);
-		dma.context         = context;
-		dma.send_count      = 0;
-		dma.request_count   = count;
-		dma.request_size    = size;
-		dma.request_list    = indices;
-		dma.request_sizes   = sizes;
-		dma.flags           = DRM_DMA_WAIT;
-		if ((r = drmDMA(fd, &dma))) {
-		    drmError(r, argv[0]);
-		    return 1;
-		}
-		for (i = 0; i < dma.granted_count; i++) {
-		    printf("%5d: index = %d, size = %d\n",
-			   i, dma.request_list[i], dma.request_sizes[i]);
-		}
-		sleep(secs);
-		drmFreeBufs(fd, dma.granted_count, indices);
-	    }
-	    break;
-	case 'b':
-	    count   = strtoul(optarg, &pt, 0);
-	    size    = strtoul(pt+1, NULL, 0);
-	    if ((r = drmAddBufs(fd, count, size, 0, 65536)) < 0) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    if (!(info = drmGetBufInfo(fd))) {
-		drmError(0, argv[0]);
-		return 1;
-	    }
-	    for (i = 0; i < info->count; i++) {
-		printf("%5d buffers of size %6d (low = %d, high = %d)\n",
-		       info->list[i].count,
-		       info->list[i].size,
-		       info->list[i].low_mark,
-		       info->list[i].high_mark);
-	    }
-	    if ((r = drmMarkBufs(fd, 0.50, 0.80))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    if (!(info = drmGetBufInfo(fd))) {
-		drmError(0, argv[0]);
-		return 1;
-	    }
-	    for (i = 0; i < info->count; i++) {
-		printf("%5d buffers of size %6d (low = %d, high = %d)\n",
-		       info->list[i].count,
-		       info->list[i].size,
-		       info->list[i].low_mark,
-		       info->list[i].high_mark);
-	    }
-	    printf("===== /proc/dri/0/mem =====\n");
-	    sprintf(buf, "cat /proc/dri/0/mem");
-	    system(buf);
-#if 1
-	    if (!(bufs = drmMapBufs(fd))) {
-		drmError(0, argv[0]);
-		return 1;
-	    }
-	    printf("===============================\n");
-	    printf( "%d bufs\n", bufs->count);
-	    for (i = 0; i < bufs->count; i++) {
-		printf( "  %4d: %8d bytes at %p\n",
-			i,
-			bufs->list[i].total,
-			bufs->list[i].address);
-	    }
-	    printf("===== /proc/dri/0/vma =====\n");
-	    sprintf(buf, "cat /proc/dri/0/vma");
-	    system(buf);
-#endif
-	    break;
-	case 'f':
-	    offset  = strtoul(optarg, &pt, 0);
-	    size    = strtoul(pt+1, NULL, 0);
-	    handle  = 0;
-	    if ((r = drmAddMap(fd, offset, size,
-			       DRM_FRAME_BUFFER, 0, &handle))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    printf("0x%08lx:0x%04lx added\n", offset, size);
-	    printf("===== /proc/dri/0/mem =====\n");
-	    sprintf(buf, "cat /proc/dri/0/mem");
-	    system(buf);
-	    break;
-	case 'r':
-	case 'R':
-	    offset  = strtoul(optarg, &pt, 0);
-	    size    = strtoul(pt+1, NULL, 0);
-	    handle  = 0;
-	    if ((r = drmAddMap(fd, offset, size,
-			       DRM_REGISTERS,
-			       c == 'R' ? DRM_READ_ONLY : 0,
-			       &handle))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    printf("0x%08lx:0x%04lx added\n", offset, size);
-	    printf("===== /proc/dri/0/mem =====\n");
-	    sprintf(buf, "cat /proc/dri/0/mem");
-	    system(buf);
-	    break;
-	case 's':
-	    size = strtoul(optarg, &pt, 0);
-	    handle = 0;
-	    if ((r = drmAddMap(fd, 0, size,
-			       DRM_SHM, DRM_CONTAINS_LOCK,
-			       &handle))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    printf("0x%04lx byte shm added at 0x%08lx\n", size, handle);
-	    sprintf(buf, "cat /proc/dri/0/vm");
-	    system(buf);
-	    break;
-	case 'P':
-	    offset  = strtoul(optarg, &pt, 0);
-	    size    = strtoul(pt+1, NULL, 0);
-	    address = NULL;
-	    if ((r = drmMap(fd, offset, size, &address))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    printf("0x%08lx:0x%04lx mapped at %p for pid %d\n",
-		   offset, size, address, getpid());
-	    printf("===== /proc/dri/0/vma =====\n");
-	    sprintf(buf, "cat /proc/dri/0/vma");
-	    system(buf);
-	    mprotect((void *)offset, size, PROT_READ);
-	    printf("===== /proc/dri/0/vma =====\n");
-	    sprintf(buf, "cat /proc/dri/0/vma");
-	    system(buf);
-	    break;
-	case 'w':
-	case 'W':
-	    offset  = strtoul(optarg, &pt, 0);
-	    size    = strtoul(pt+1, NULL, 0);
-	    address = NULL;
-	    if ((r = drmMap(fd, offset, size, &address))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    printf("0x%08lx:0x%04lx mapped at %p for pid %d\n",
-		   offset, size, address, getpid());
-	    printf("===== /proc/%d/maps =====\n", getpid());
-	    sprintf(buf, "cat /proc/%d/maps", getpid());
-	    system(buf);
-	    printf("===== /proc/dri/0/mem =====\n");
-	    sprintf(buf, "cat /proc/dri/0/mem");
-	    system(buf);
-	    printf("===== /proc/dri/0/vma =====\n");
-	    sprintf(buf, "cat /proc/dri/0/vma");
-	    system(buf);
-	    printf("===== READING =====\n");
-	    for (i = 0; i < 0x10; i++)
-		printf("%02x ", (unsigned int)((unsigned char *)address)[i]);
-	    printf("\n");
-	    if (c == 'w') {
-		printf("===== WRITING =====\n");
-		for (i = 0; i < size; i+=2) {
-		    ((char *)address)[i]   = i & 0xff;
-		    ((char *)address)[i+1] = i & 0xff;
-		}
-	    }
-	    printf("===== READING =====\n");
-	    for (i = 0; i < 0x10; i++)
-		printf("%02x ", (unsigned int)((unsigned char *)address)[i]);
-	    printf("\n");
-	    printf("===== /proc/dri/0/vma =====\n");
-	    sprintf(buf, "cat /proc/dri/0/vma");
-	    system(buf);
-	    break;
-	case 'L':
-	    context = strtoul(optarg, &pt, 0);
-	    offset  = strtoul(pt+1, &pt, 0);
-	    size    = strtoul(pt+1, &pt, 0);
-	    loops   = strtoul(pt+1, NULL, 0);
-	    address = NULL;
-	    if ((r = drmMap(fd, offset, size, &address))) {
-		drmError(r, argv[0]);
-		return 1;
-	    }
-	    lock       = address;
-#if 1
-	    {
-		int            counter = 0;
-		struct timeval loop_start, loop_end;
-		struct timeval lock_start, lock_end;
-		double         wt;
-#define HISTOSIZE 9
-		int            histo[HISTOSIZE];
-		int            output = 0;
-		int            fast   = 0;
-
-		if (loops < 0) {
-		    loops = -loops;
-		    ++output;
-		}
-
-		for (i = 0; i < HISTOSIZE; i++) histo[i] = 0;
-
-		gettimeofday(&loop_start, NULL);
-		for (i = 0; i < loops; i++) {
-		    gettimeofday(&lock_start, NULL);
-		    DRM_LIGHT_LOCK_COUNT(fd,lock,context,fast);
-		    gettimeofday(&lock_end, NULL);
-		    DRM_UNLOCK(fd,lock,context);
-		    ++counter;
-		    wt = usec(&lock_end, &lock_start);
-		    if      (wt <=      2.5) ++histo[8];
-		    if      (wt <       5.0) ++histo[0];
-		    else if (wt <      50.0) ++histo[1];
-		    else if (wt <     500.0) ++histo[2];
-		    else if (wt <    5000.0) ++histo[3];
-		    else if (wt <   50000.0) ++histo[4];
-		    else if (wt <  500000.0) ++histo[5];
-		    else if (wt < 5000000.0) ++histo[6];
-		    else                     ++histo[7];
-		    if (output) printf( "%.2f uSec, %d fast\n", wt, fast);
-		}
-		gettimeofday(&loop_end, NULL);
-		printf( "Average wait time = %.2f usec, %d fast\n",
-			usec(&loop_end, &loop_start) /  counter, fast);
-		printf( "%9d <=     2.5 uS\n", histo[8]);
-		printf( "%9d <        5 uS\n", histo[0]);
-		printf( "%9d <       50 uS\n", histo[1]);
-		printf( "%9d <      500 uS\n", histo[2]);
-		printf( "%9d <     5000 uS\n", histo[3]);
-		printf( "%9d <    50000 uS\n", histo[4]);
-		printf( "%9d <   500000 uS\n", histo[5]);
-		printf( "%9d <  5000000 uS\n", histo[6]);
-		printf( "%9d >= 5000000 uS\n", histo[7]);
-	    }
-#else
-	    printf( "before lock: 0x%08x\n", lock->lock);
-	    printf( "lock: 0x%08x\n", lock->lock);
-	    sleep(5);
-	    printf( "unlock: 0x%08x\n", lock->lock);
-#endif
-	    break;
-	default:
-	    fprintf( stderr, "Usage: drmstat [options]\n" );
-	    return 1;
-	}
-
-    return r; 
-}
-
-int xf86ConfigDRI[10];
diff --git a/tests/etnaviv/Makefile.am b/tests/etnaviv/Makefile.am
index 0631864..226baee 100644
--- a/tests/etnaviv/Makefile.am
+++ b/tests/etnaviv/Makefile.am
@@ -28,6 +28,7 @@
 	write_bmp.h
 
 etnaviv_cmd_stream_test_LDADD = \
+	$(top_builddir)/libdrm.la \
 	$(top_builddir)/etnaviv/libdrm_etnaviv.la
 
 etnaviv_cmd_stream_test_SOURCES = \
diff --git a/tests/etnaviv/etnaviv_2d_test.c b/tests/etnaviv/etnaviv_2d_test.c
index 10751c7..8dd77b6 100644
--- a/tests/etnaviv/etnaviv_2d_test.c
+++ b/tests/etnaviv/etnaviv_2d_test.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
diff --git a/tests/etnaviv/etnaviv_bo_cache_test.c b/tests/etnaviv/etnaviv_bo_cache_test.c
index fb01f8d..7fb0629 100644
--- a/tests/etnaviv/etnaviv_bo_cache_test.c
+++ b/tests/etnaviv/etnaviv_bo_cache_test.c
@@ -24,10 +24,6 @@
  *    Christian Gmeiner <christian.gmeiner@gmail.com>
  */
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 #undef NDEBUG
 #include <assert.h>
 
diff --git a/tests/etnaviv/meson.build b/tests/etnaviv/meson.build
new file mode 100644
index 0000000..8b4a3cf
--- /dev/null
+++ b/tests/etnaviv/meson.build
@@ -0,0 +1,45 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+inc_etnaviv_tests = [inc_root, inc_drm, include_directories('../../etnaviv')]
+
+etnaviv_2d_test = executable(
+  'etnaviv_2d_test',
+  files('etnaviv_2d_test.c', 'write_bmp.c'),
+  include_directories : inc_etnaviv_tests,
+  link_with : [libdrm, libdrm_etnaviv],
+  install : with_install_tests,
+)
+
+etnaviv_cmd_stream_test = executable(
+  'etnaviv_cmd_stream_test',
+  files('etnaviv_cmd_stream_test.c'),
+  include_directories : inc_etnaviv_tests,
+  link_with : [libdrm, libdrm_etnaviv],
+  install : with_install_tests,
+)
+
+etnaviv_bo_cache_test = executable(
+  'etnaviv_bo_cache_test',
+  files('etnaviv_bo_cache_test.c'),
+  include_directories : inc_etnaviv_tests,
+  link_with : [libdrm, libdrm_etnaviv],
+  install : with_install_tests,
+)
diff --git a/tests/etnaviv/write_bmp.c b/tests/etnaviv/write_bmp.c
index 7ae0646..f7b6bc6 100644
--- a/tests/etnaviv/write_bmp.c
+++ b/tests/etnaviv/write_bmp.c
@@ -63,7 +63,7 @@
 	unsigned int unused[12];
 } __attribute__((__packed__));
 
-static int
+static void
 bmp_header_write(int fd, int width, int height, int bgra, int noflip, int alpha)
 {
 	struct bmp_header bmp_header = {
@@ -98,8 +98,6 @@
 
 	write(fd, &bmp_header, sizeof(struct bmp_header));
 	write(fd, &dib_header, sizeof(struct dib_header));
-
-	return 0;
 }
 
 void
diff --git a/tests/exynos/exynos_fimg2d_event.c b/tests/exynos/exynos_fimg2d_event.c
index 9ed5a30..353e087 100644
--- a/tests/exynos/exynos_fimg2d_event.c
+++ b/tests/exynos/exynos_fimg2d_event.c
@@ -1,17 +1,24 @@
 /*
  * Copyright (C) 2015 - Tobias Jakobi
  *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation, either version 2 of the License,
- * or (at your option) any later version.
+ * 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:
  *
- * It 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 it. If not, see <http://www.gnu.org/licenses/>.
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
  */
 
 #include <unistd.h>
diff --git a/tests/exynos/exynos_fimg2d_perf.c b/tests/exynos/exynos_fimg2d_perf.c
index 1699bba..97691a7 100644
--- a/tests/exynos/exynos_fimg2d_perf.c
+++ b/tests/exynos/exynos_fimg2d_perf.c
@@ -1,17 +1,24 @@
 /*
  * Copyright (C) 2015 - Tobias Jakobi
  *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation, either version 2 of the License,
- * or (at your option) any later version.
+ * 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:
  *
- * It 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 it. If not, see <http://www.gnu.org/licenses/>.
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
  */
 
 #include <stdlib.h>
@@ -267,13 +274,6 @@
 		goto out;
 	}
 
-	if (bufw == 0 || bufh == 0) {
-		fprintf(stderr, "error: buffer width/height should be non-zero.\n");
-		ret = -1;
-
-		goto out;
-	}
-
 	fd = drmOpen("exynos", NULL);
 	if (fd < 0) {
 		fprintf(stderr, "error: failed to open drm\n");
diff --git a/tests/exynos/exynos_fimg2d_test.c b/tests/exynos/exynos_fimg2d_test.c
index 797fb6e..99bb923 100644
--- a/tests/exynos/exynos_fimg2d_test.c
+++ b/tests/exynos/exynos_fimg2d_test.c
@@ -3,17 +3,26 @@
  * Authors:
  *	Inki Dae <inki.dae@samsung.com>
  *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -59,7 +68,6 @@
 		if (!connector) {
 			fprintf(stderr, "could not get connector %i: %s\n",
 				resources->connectors[i], strerror(errno));
-			drmModeFreeConnector(connector);
 			continue;
 		}
 
@@ -98,7 +106,6 @@
 		if (!c->encoder) {
 			fprintf(stderr, "could not get encoder %i: %s\n",
 				resources->encoders[i], strerror(errno));
-			drmModeFreeEncoder(c->encoder);
 			continue;
 		}
 
@@ -264,7 +271,8 @@
 		userptr = (unsigned long)malloc(size);
 		if (!userptr) {
 			fprintf(stderr, "failed to allocate userptr.\n");
-			return -EFAULT;
+			ret = -EFAULT;
+			goto fail;
 		}
 
 		src_img.user_ptr[0].userptr = userptr;
@@ -469,7 +477,8 @@
 		userptr = (unsigned long)malloc(size);
 		if (!userptr) {
 			fprintf(stderr, "failed to allocate userptr.\n");
-			return -EFAULT;
+			ret = -EFAULT;
+			goto fail;
 		}
 
 		src_img.user_ptr[0].userptr = userptr;
@@ -520,9 +529,10 @@
 fail:
 	g2d_fini(ctx);
 
-	return 0;
+	return ret;
 }
 
+#ifdef EXYNOS_G2D_USERPTR_TEST
 static int g2d_blend_test(struct exynos_device *dev,
 					struct exynos_bo *src,
 					struct exynos_bo *dst,
@@ -557,7 +567,8 @@
 		userptr = (unsigned long)malloc(size);
 		if (!userptr) {
 			fprintf(stderr, "failed to allocate userptr.\n");
-			return -EFAULT;
+			ret = -EFAULT;
+			goto fail;
 		}
 
 		src_img.user_ptr[0].userptr = userptr;
@@ -619,8 +630,9 @@
 fail:
 	g2d_fini(ctx);
 
-	return 0;
+	return ret;
 }
+#endif
 
 static int g2d_checkerboard_test(struct exynos_device *dev,
 					struct exynos_bo *src,
@@ -645,8 +657,8 @@
 	dst_y = 0;
 
 	checkerboard = create_checkerboard_pattern(screen_width / 32, screen_height / 32, 32);
-	if (checkerboard == NULL) {
-		ret = -1;
+	if (!checkerboard) {
+		ret = -EFAULT;
 		goto fail;
 	}
 
@@ -755,8 +767,8 @@
 
 	dev = exynos_device_create(fd);
 	if (!dev) {
-		drmClose(dev->fd);
-		return -EFAULT;
+		ret = -EFAULT;
+		goto err_drm_close;
 	}
 
 	resources = drmModeGetResources(dev->fd);
@@ -764,7 +776,7 @@
 		fprintf(stderr, "drmModeGetResources failed: %s\n",
 				strerror(errno));
 		ret = -EFAULT;
-		goto err_drm_close;
+		goto err_dev_destory;
 	}
 
 	connector_find_mode(dev->fd, &con, resources);
@@ -773,7 +785,7 @@
 	if (!con.mode) {
 		fprintf(stderr, "failed to find usable connector\n");
 		ret = -EFAULT;
-		goto err_drm_close;
+		goto err_dev_destory;
 	}
 
 	screen_width = con.mode->hdisplay;
@@ -782,7 +794,7 @@
 	if (screen_width == 0 || screen_height == 0) {
 		fprintf(stderr, "failed to find sane resolution on connector\n");
 		ret = -EFAULT;
-		goto err_drm_close;
+		goto err_dev_destory;
 	}
 
 	printf("screen width = %d, screen height = %d\n", screen_width,
@@ -791,7 +803,7 @@
 	bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
 	if (!bo) {
 		ret = -EFAULT;
-		goto err_drm_close;
+		goto err_dev_destory;
 	}
 
 	handles[0] = bo->handle;
@@ -864,7 +876,7 @@
 	 *
 	 * Disable the test for now, until the kernel code has been sanitized.
 	 */
-#if 0
+#ifdef EXYNOS_G2D_USERPTR_TEST
 	ret  = g2d_blend_test(dev, src, bo, G2D_IMGBUF_USERPTR);
 	if (ret < 0)
 		fprintf(stderr, "failed to test blend operation.\n");
@@ -882,9 +894,11 @@
 err_destroy_buffer:
 	exynos_destroy_buffer(bo);
 
-err_drm_close:
-	drmClose(dev->fd);
+err_dev_destory:
 	exynos_device_destroy(dev);
 
-	return 0;
+err_drm_close:
+	drmClose(fd);
+
+	return ret;
 }
diff --git a/tests/exynos/meson.build b/tests/exynos/meson.build
new file mode 100644
index 0000000..940c3ce
--- /dev/null
+++ b/tests/exynos/meson.build
@@ -0,0 +1,54 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+inc_exynos = include_directories('../../exynos')
+
+if with_libkms
+  exynos_fimg2d_test = executable(
+    'exynos_fimg2d_test',
+    files('exynos_fimg2d_test.c'),
+    c_args : warn_c_args,
+    include_directories : [inc_root, inc_drm, inc_exynos,
+                           include_directories('../../libkms')],
+    link_with : [libdrm, libkms, libdrm_exynos],
+    dependencies : dep_threads,
+    install : with_install_tests,
+  )
+endif
+
+exynos_fimg2d_perf = executable(
+  'exynos_fimg2d_perf',
+  files('exynos_fimg2d_perf.c'),
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_drm, inc_exynos],
+  link_with : [libdrm, libdrm_exynos],
+  dependencies : dep_threads,
+  install : with_install_tests,
+)
+
+exynos_fimg2d_event = executable(
+  'exynos_fimg2d_event',
+  files('exynos_fimg2d_event.c'),
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_drm, inc_exynos],
+  link_with : [libdrm, libdrm_exynos],
+  dependencies : dep_threads,
+  install : with_install_tests,
+)
diff --git a/tests/kms/kms-steal-crtc.c b/tests/kms/kms-steal-crtc.c
index 4b830d2..cd40758 100644
--- a/tests/kms/kms-steal-crtc.c
+++ b/tests/kms/kms-steal-crtc.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
diff --git a/tests/kms/kms-universal-planes.c b/tests/kms/kms-universal-planes.c
index 89057bb..2163c98 100644
--- a/tests/kms/kms-universal-planes.c
+++ b/tests/kms/kms-universal-planes.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <fcntl.h>
 #include <getopt.h>
 #include <stdbool.h>
diff --git a/tests/kms/libkms-test-crtc.c b/tests/kms/libkms-test-crtc.c
index 3adb490..2c28fac 100644
--- a/tests/kms/libkms-test-crtc.c
+++ b/tests/kms/libkms-test-crtc.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include "libkms-test.h"
 
 struct kms_crtc *kms_crtc_create(struct kms_device *device, uint32_t id)
diff --git a/tests/kms/libkms-test-device.c b/tests/kms/libkms-test-device.c
index 53c7349..d3bb11c 100644
--- a/tests/kms/libkms-test-device.c
+++ b/tests/kms/libkms-test-device.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
@@ -67,7 +63,7 @@
 
 	device->screens = calloc(res->count_connectors, sizeof(screen));
 	if (!device->screens)
-		return;
+		goto err_free_resources;
 
 	for (i = 0; i < res->count_connectors; i++) {
 		unsigned int *count;
@@ -97,6 +93,7 @@
 		device->num_screens++;
 	}
 
+err_free_resources:
 	drmModeFreeResources(res);
 }
 
@@ -112,7 +109,7 @@
 
 	device->crtcs = calloc(res->count_crtcs, sizeof(crtc));
 	if (!device->crtcs)
-		return;
+		goto err_free_resources;
 
 	for (i = 0; i < res->count_crtcs; i++) {
 		crtc = kms_crtc_create(device, res->crtcs[i]);
@@ -123,6 +120,7 @@
 		device->num_crtcs++;
 	}
 
+err_free_resources:
 	drmModeFreeResources(res);
 }
 
@@ -138,7 +136,7 @@
 
 	device->planes = calloc(res->count_planes, sizeof(plane));
 	if (!device->planes)
-		return;
+		goto err_free_resources;
 
 	for (i = 0; i < res->count_planes; i++) {
 		plane = kms_plane_create(device, res->planes[i]);
@@ -149,6 +147,7 @@
 		device->num_planes++;
 	}
 
+err_free_resources:
 	drmModeFreePlaneResources(res);
 }
 
diff --git a/tests/kms/libkms-test-framebuffer.c b/tests/kms/libkms-test-framebuffer.c
index c9e5ad3..9bb2d95 100644
--- a/tests/kms/libkms-test-framebuffer.c
+++ b/tests/kms/libkms-test-framebuffer.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <string.h>
 
diff --git a/tests/kms/libkms-test-plane.c b/tests/kms/libkms-test-plane.c
index 8eb78af..6c40a3c 100644
--- a/tests/kms/libkms-test-plane.c
+++ b/tests/kms/libkms-test-plane.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <string.h>
 
diff --git a/tests/kms/libkms-test-screen.c b/tests/kms/libkms-test-screen.c
index 3369022..bbe972a 100644
--- a/tests/kms/libkms-test-screen.c
+++ b/tests/kms/libkms-test-screen.c
@@ -21,10 +21,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <string.h>
 
diff --git a/tests/kms/meson.build b/tests/kms/meson.build
new file mode 100644
index 0000000..1f7f724
--- /dev/null
+++ b/tests/kms/meson.build
@@ -0,0 +1,49 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+
+libkms_test = static_library(
+  'kms-test',
+  files(
+    'libkms-test-crtc.c', 'libkms-test-device.c', 'libkms-test-framebuffer.c',
+    'libkms-test-plane.c', 'libkms-test-screen.c',
+  ),
+  include_directories : [inc_root, inc_tests, inc_drm],
+  link_with : libdrm,
+  c_args : warn_c_args,
+)
+
+kms_steal_crtc = executable(
+  'kms-steal-crtc',
+  files('kms-steal-crtc.c'),
+  dependencies : dep_cairo,
+  include_directories : [inc_root, inc_tests, inc_drm],
+  link_with : [libkms_test, libutil],
+  install : with_install_tests,
+)
+
+kms_universal_planes = executable(
+  'kms-universal-planes',
+  files('kms-universal-planes.c'),
+  dependencies : dep_cairo,
+  include_directories : [inc_root, inc_tests, inc_drm],
+  link_with : [libkms_test],
+  install : with_install_tests,
+)
diff --git a/tests/kmstest/meson.build b/tests/kmstest/meson.build
new file mode 100644
index 0000000..a47d495
--- /dev/null
+++ b/tests/kmstest/meson.build
@@ -0,0 +1,30 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+kmstest = executable(
+  'kmstest',
+  files('main.c'),
+  c_args : warn_c_args,
+  include_directories : [
+    inc_root, inc_tests, include_directories('../../libkms'), inc_drm,
+  ],
+  link_with : [libutil, libkms, libdrm],
+  install : with_install_tests,
+)
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 0000000..fdf950b
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,86 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+inc_tests = include_directories('.')
+
+subdir('util')
+subdir('kms')
+subdir('modeprint')
+subdir('proptest')
+subdir('modetest')
+subdir('vbltest')
+if with_libkms
+  subdir('kmstest')
+endif
+if with_radeon
+  subdir('radeon')
+endif
+if with_amdgpu
+  subdir('amdgpu')
+endif
+if with_exynos
+  subdir('exynos')
+endif
+if with_tegra
+  subdir('tegra')
+endif
+if with_etnaviv
+  subdir('etnaviv')
+endif
+if with_nouveau
+  subdir('nouveau')
+endif
+
+drmsl = executable(
+  'drmsl',
+  files('drmsl.c'),
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  c_args : warn_c_args,
+)
+
+hash = executable(
+  'hash',
+  files('hash.c'),
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  c_args : warn_c_args,
+)
+
+random = executable(
+  'random',
+  files('random.c'),
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  c_args : warn_c_args,
+)
+
+drmdevice = executable(
+  'drmdevice',
+  files('drmdevice.c'),
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  c_args : warn_c_args,
+)
+
+test('random', random, timeout : 240)
+test('hash', hash)
+test('drmsl', drmsl)
+test('drmdevice', drmdevice)
diff --git a/tests/modeprint/meson.build b/tests/modeprint/meson.build
new file mode 100644
index 0000000..5f0eb24
--- /dev/null
+++ b/tests/modeprint/meson.build
@@ -0,0 +1,29 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+modeprint = executable(
+  'modeprint',
+  files('modeprint.c'),
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_tests, inc_drm],
+  link_with : libdrm,
+  dependencies : dep_threads,
+  install : with_install_tests,
+)
diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c
index 0d85410..c81dd91 100644
--- a/tests/modeprint/modeprint.c
+++ b/tests/modeprint/modeprint.c
@@ -244,7 +244,7 @@
 	printf("\thandle    : %i\n", fb->handle);
 	printf("\twidth     : %i\n", fb->width);
 	printf("\theight    : %i\n", fb->height);
-	printf("\tpitch     : %i\n", fb->pitch);;
+	printf("\tpitch     : %i\n", fb->pitch);
 	printf("\tbpp       : %i\n", fb->bpp);
 	printf("\tdepth     : %i\n", fb->depth);
 	printf("\tbuffer_id : %i\n", fb->handle);
diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
index 4fd310b..9b635c0 100644
--- a/tests/modetest/buffers.c
+++ b/tests/modetest/buffers.c
@@ -24,10 +24,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
diff --git a/tests/modetest/cursor.c b/tests/modetest/cursor.c
index 6de82a4..829bced 100644
--- a/tests/modetest/cursor.c
+++ b/tests/modetest/cursor.c
@@ -22,10 +22,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
diff --git a/tests/modetest/meson.build b/tests/modetest/meson.build
new file mode 100644
index 0000000..2a08184
--- /dev/null
+++ b/tests/modetest/meson.build
@@ -0,0 +1,29 @@
+# Copyright © 2018 Intel Corporation
+
+# 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 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.
+
+modetest = executable(
+  'modetest',
+  files('buffers.c', 'cursor.c', 'modetest.c'),
+  c_args : [warn_c_args, '-Wno-pointer-arith'],
+  include_directories : [inc_root, inc_tests, inc_drm],
+  dependencies : [dep_threads, dep_cairo],
+  link_with : [libdrm, libutil],
+  install : with_install_tests,
+)
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index cd91119..62957d8 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -38,10 +38,6 @@
  *       the mode has been programmed, along with possible test patterns.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <assert.h>
 #include <ctype.h>
 #include <stdbool.h>
@@ -174,6 +170,15 @@
 
 static bit_name_fn(mode_flag)
 
+static void dump_fourcc(uint32_t fourcc)
+{
+	printf(" %c%c%c%c",
+		fourcc,
+		fourcc >> 8,
+		fourcc >> 16,
+		fourcc >> 24);
+}
+
 static void dump_encoders(struct device *dev)
 {
 	drmModeEncoder *encoder;
@@ -242,6 +247,89 @@
 	drmModeFreePropertyBlob(blob);
 }
 
+static const char *modifier_to_string(uint64_t modifier)
+{
+	switch (modifier) {
+	case DRM_FORMAT_MOD_INVALID:
+		return "INVALID";
+	case DRM_FORMAT_MOD_LINEAR:
+		return "LINEAR";
+	case I915_FORMAT_MOD_X_TILED:
+		return "X_TILED";
+	case I915_FORMAT_MOD_Y_TILED:
+		return "Y_TILED";
+	case I915_FORMAT_MOD_Yf_TILED:
+		return "Yf_TILED";
+	case I915_FORMAT_MOD_Y_TILED_CCS:
+		return "Y_TILED_CCS";
+	case I915_FORMAT_MOD_Yf_TILED_CCS:
+		return "Yf_TILED_CCS";
+	case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
+		return "SAMSUNG_64_32_TILE";
+	case DRM_FORMAT_MOD_VIVANTE_TILED:
+		return "VIVANTE_TILED";
+	case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
+		return "VIVANTE_SUPER_TILED";
+	case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
+		return "VIVANTE_SPLIT_TILED";
+	case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
+		return "VIVANTE_SPLIT_SUPER_TILED";
+	case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED:
+		return "NVIDIA_TEGRA_TILED";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0):
+		return "NVIDIA_16BX2_BLOCK(0)";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1):
+		return "NVIDIA_16BX2_BLOCK(1)";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2):
+		return "NVIDIA_16BX2_BLOCK(2)";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3):
+		return "NVIDIA_16BX2_BLOCK(3)";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4):
+		return "NVIDIA_16BX2_BLOCK(4)";
+	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5):
+		return "NVIDIA_16BX2_BLOCK(5)";
+	case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
+		return "MOD_BROADCOM_VC4_T_TILED";
+	default:
+		return "(UNKNOWN MODIFIER)";
+	}
+}
+
+static void dump_in_formats(struct device *dev, uint32_t blob_id)
+{
+	uint32_t i, j;
+	drmModePropertyBlobPtr blob;
+	struct drm_format_modifier_blob *header;
+	uint32_t *formats;
+	struct drm_format_modifier *modifiers;
+
+	printf("\t\tin_formats blob decoded:\n");
+	blob = drmModeGetPropertyBlob(dev->fd, blob_id);
+	if (!blob) {
+		printf("\n");
+		return;
+	}
+
+	header = blob->data;
+	formats = (uint32_t *) ((char *) header + header->formats_offset);
+	modifiers = (struct drm_format_modifier *)
+		((char *) header + header->modifiers_offset);
+
+	for (i = 0; i < header->count_formats; i++) {
+		printf("\t\t\t");
+		dump_fourcc(formats[i]);
+		printf(": ");
+		for (j = 0; j < header->count_modifiers; j++) {
+			uint64_t mask = 1ULL << i;
+			if (modifiers[j].formats & mask)
+				printf(" %s", modifier_to_string(modifiers[j].modifier));
+		}
+		printf("\n");
+	}
+
+	drmModeFreePropertyBlob(blob);
+}
+
 static void dump_prop(struct device *dev, drmModePropertyPtr prop,
 		      uint32_t prop_id, uint64_t value)
 {
@@ -319,6 +407,9 @@
 		printf(" %"PRId64"\n", value);
 	else
 		printf(" %"PRIu64"\n", value);
+
+	if (strcmp(prop->name, "IN_FORMATS") == 0)
+		dump_in_formats(dev, value);
 }
 
 static void dump_connectors(struct device *dev)
@@ -443,7 +534,7 @@
 
 		printf("  formats:");
 		for (j = 0; j < ovr->count_formats; j++)
-			printf(" %4.4s", (char *)&ovr->formats[j]);
+			dump_fourcc(ovr->formats[j]);
 		printf("\n");
 
 		if (plane->props) {
@@ -524,7 +615,6 @@
 		return NULL;
 
 	drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
-	drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
 
 	res->res = drmModeGetResources(dev->fd);
 	if (!res->res) {
@@ -562,10 +652,13 @@
 	for (i = 0; i < res->res->count_connectors; i++) {
 		struct connector *connector = &res->connectors[i];
 		drmModeConnector *conn = connector->connector;
+		int num;
 
-		asprintf(&connector->name, "%s-%u",
+		num = asprintf(&connector->name, "%s-%u",
 			 util_lookup_connector_type_name(conn->connector_type),
 			 conn->connector_type_id);
+		if (num < 0)
+			goto error;
 	}
 
 #define get_properties(_res, __res, type, Type)					\
@@ -997,7 +1090,8 @@
 		if (!format_support(ovr, p->fourcc))
 			continue;
 
-		if ((ovr->possible_crtcs & (1 << pipe)) && !ovr->crtc_id) {
+		if ((ovr->possible_crtcs & (1 << pipe)) &&
+		    (ovr->crtc_id == 0 || ovr->crtc_id == p->crtc_id)) {
 			plane_id = ovr->plane_id;
 			break;
 		}
diff --git a/tests/nouveau/meson.build b/tests/nouveau/meson.build
new file mode 100644
index 0000000..f5d73c1
--- /dev/null
+++ b/tests/nouveau/meson.build
@@ -0,0 +1,30 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+threaded = executable(
+  'threaded',
+  files('threaded.c'),
+  dependencies : [dep_dl, dep_threads],
+  include_directories : [inc_root, inc_drm, include_directories('../../nouveau')],
+  link_with : [libdrm, libdrm_nouveau],
+  c_args : warn_c_args,
+)
+
+test('threaded', threaded)
diff --git a/tests/nouveau/threaded.c b/tests/nouveau/threaded.c
index 281af46..3669bcd 100644
--- a/tests/nouveau/threaded.c
+++ b/tests/nouveau/threaded.c
@@ -20,10 +20,6 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 #include <sys/ioctl.h>
 #include <dlfcn.h>
 #include <fcntl.h>
diff --git a/tests/planetest/atomictest.c b/tests/planetest/atomictest.c
index 5fec911..891d242 100644
--- a/tests/planetest/atomictest.c
+++ b/tests/planetest/atomictest.c
@@ -47,7 +47,7 @@
 	struct sp_plane **plane = NULL;
 	struct sp_crtc *test_crtc;
 	fd_set fds;
-	drmModePropertySetPtr pset;
+	drmModeAtomicReqPtr pset;
 	drmEventContext event_context = {
 		.version = DRM_EVENT_CONTEXT_VERSION,
 		.page_flip_handler = page_flip_handler,
@@ -100,7 +100,7 @@
 		fill_bo(plane[i]->bo, 0xFF, 0xFF, 0xFF, 0xFF);
 	}
 
-	pset = drmModePropertySetAlloc();
+	pset = drmModeAtomicAlloc();
 	if (!pset) {
 		printf("Failed to allocate the property set\n");
 		goto out;
@@ -124,8 +124,8 @@
 			}
 		}
 
-		ret = drmModePropertySetCommit(dev->fd,
-				DRM_MODE_PAGE_FLIP_EVENT, NULL, pset);
+		ret = drmModeAtomicCommit(dev->fd, pset,
+					DRM_MODE_PAGE_FLIP_EVENT, NULL);
 		if (ret) {
 			printf("failed to commit properties ret=%d\n", ret);
 			goto out;
@@ -139,7 +139,7 @@
 			drmHandleEvent(dev->fd, &event_context);
 	}
 
-	drmModePropertySetFree(pset);
+	drmModeAtomicFree(pset);
 
 	for (i = 0; i < num_test_planes; i++)
 		put_sp_plane(plane[i]);
diff --git a/tests/planetest/modeset.c b/tests/planetest/modeset.c
index 037814e..b8f6690 100644
--- a/tests/planetest/modeset.c
+++ b/tests/planetest/modeset.c
@@ -15,7 +15,7 @@
 {
 	int ret;
 	struct drm_mode_create_blob create_blob;
-	drmModePropertySetPtr pset;
+	drmModeAtomicReqPtr pset;
 
 	memset(&create_blob, 0, sizeof(create_blob));
 	create_blob.length = sizeof(struct drm_mode_modeinfo);
@@ -27,28 +27,28 @@
 		return ret;
 	}
 
-	pset = drmModePropertySetAlloc();
+	pset = drmModeAtomicAlloc();
 	if (!pset) {
 		printf("Failed to allocate property set");
 		return -1;
 	}
 
-	ret = drmModePropertySetAdd(pset, crtc->crtc->crtc_id,
+	ret = drmModeAtomicAddProperty(pset, crtc->crtc->crtc_id,
 				    crtc->mode_pid, create_blob.blob_id) ||
-	      drmModePropertySetAdd(pset, crtc->crtc->crtc_id,
+	      drmModeAtomicAddProperty(pset, crtc->crtc->crtc_id,
 				    crtc->active_pid, 1) ||
-		drmModePropertySetAdd(pset, conn->conn->connector_id,
+	      drmModeAtomicAddProperty(pset, conn->conn->connector_id,
 				conn->crtc_id_pid, crtc->crtc->crtc_id);
 	if (ret) {
 		printf("Failed to add blob %d to pset", create_blob.blob_id);
-		drmModePropertySetFree(pset);
+		drmModeAtomicFree(pset);
 		return ret;
 	}
 
-	ret = drmModePropertySetCommit(dev->fd, DRM_MODE_ATOMIC_ALLOW_MODESET,
-					NULL, pset);
+	ret = drmModeAtomicCommit(dev->fd, pset, DRM_MODE_ATOMIC_ALLOW_MODESET,
+					NULL);
 
-	drmModePropertySetFree(pset);
+	drmModeAtomicFree(pset);
 
 	if (ret) {
 		printf("Failed to commit pset ret=%d\n", ret);
@@ -190,7 +190,7 @@
 	return ret;
 }
 int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane,
-		drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y)
+		drmModeAtomicReqPtr pset, struct sp_crtc *crtc, int x, int y)
 {
 	int ret;
 	uint32_t w, h;
@@ -203,25 +203,25 @@
 	if ((h + y) > crtc->crtc->mode.vdisplay)
 		h = crtc->crtc->mode.vdisplay - y;
 
-	ret = drmModePropertySetAdd(pset, plane->plane->plane_id,
+	ret = drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->crtc_pid, crtc->crtc->crtc_id)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->fb_pid, plane->bo->fb_id)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->crtc_x_pid, x)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->crtc_y_pid, y)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->crtc_w_pid, w)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->crtc_h_pid, h)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->src_x_pid, 0)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->src_y_pid, 0)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->src_w_pid, w << 16)
-		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
+		|| drmModeAtomicAddProperty(pset, plane->plane->plane_id,
 			plane->src_h_pid, h << 16);
 	if (ret) {
 		printf("failed to add properties to the set\n");
diff --git a/tests/planetest/modeset.h b/tests/planetest/modeset.h
index 7e96574..5499959 100644
--- a/tests/planetest/modeset.h
+++ b/tests/planetest/modeset.h
@@ -14,6 +14,6 @@
 		struct sp_crtc *crtc, int x, int y);
 
 int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane,
-		drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y);
+		drmModeAtomicReqPtr pset, struct sp_crtc *crtc, int x, int y);
 
 #endif /* __MODESET_H_INCLUDED__ */
diff --git a/tests/proptest/meson.build b/tests/proptest/meson.build
new file mode 100644
index 0000000..22d7473
--- /dev/null
+++ b/tests/proptest/meson.build
@@ -0,0 +1,28 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+proptest = executable(
+  'proptest',
+  files('proptest.c'),
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_tests, inc_drm],
+  link_with : [libdrm, libutil],
+  install : with_install_tests,
+)
diff --git a/tests/radeon/meson.build b/tests/radeon/meson.build
new file mode 100644
index 0000000..9e4f916
--- /dev/null
+++ b/tests/radeon/meson.build
@@ -0,0 +1,27 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+radeon_ttm = executable(
+  'radeon_ttm',
+  files('rbo.c', 'radeon_ttm.c'),
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  c_args : warn_c_args,
+)
diff --git a/tests/tegra/meson.build b/tests/tegra/meson.build
new file mode 100644
index 0000000..9c74ac4
--- /dev/null
+++ b/tests/tegra/meson.build
@@ -0,0 +1,27 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+openclose = executable(
+  'openclose',
+  files('openclose.c'),
+  include_directories : [inc_root, inc_drm, include_directories('../../tegra')],
+  c_args : warn_c_args,
+  link_with : [libdrm, libdrm_tegra],
+)
diff --git a/tests/tegra/openclose.c b/tests/tegra/openclose.c
index 881d8aa..f80f52d 100644
--- a/tests/tegra/openclose.c
+++ b/tests/tegra/openclose.c
@@ -20,10 +20,6 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
diff --git a/tests/util/format.c b/tests/util/format.c
index 043cfe7..15ac5e1 100644
--- a/tests/util/format.c
+++ b/tests/util/format.c
@@ -23,10 +23,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/tests/util/kms.c b/tests/util/kms.c
index 959b688..8b3e787 100644
--- a/tests/util/kms.c
+++ b/tests/util/kms.c
@@ -37,10 +37,6 @@
  *       the mode has been programmed, along with possible test patterns.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -79,6 +75,7 @@
 	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
 	{ DRM_MODE_ENCODER_DSI, "DSI" },
 	{ DRM_MODE_ENCODER_DPMST, "DPMST" },
+	{ DRM_MODE_ENCODER_DPI, "DPI" },
 };
 
 const char *util_lookup_encoder_type_name(unsigned int type)
@@ -117,6 +114,7 @@
 	{ DRM_MODE_CONNECTOR_eDP, "eDP" },
 	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
 	{ DRM_MODE_CONNECTOR_DSI, "DSI" },
+	{ DRM_MODE_CONNECTOR_DPI, "DPI" },
 };
 
 const char *util_lookup_connector_type_name(unsigned int type)
@@ -145,6 +143,7 @@
 	"virtio_gpu",
 	"mediatek",
 	"meson",
+	"pl111",
 };
 
 int util_open(const char *device, const char *module)
diff --git a/tests/util/meson.build b/tests/util/meson.build
new file mode 100644
index 0000000..7fa1a4b
--- /dev/null
+++ b/tests/util/meson.build
@@ -0,0 +1,28 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+
+libutil = static_library(
+  'util',
+  [files('format.c', 'kms.c', 'pattern.c'), config_file],
+  include_directories : [inc_root, inc_drm],
+  link_with : libdrm,
+  dependencies : dep_cairo
+)
diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 00b08a8..9fa0a41 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -23,10 +23,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,7 +30,7 @@
 
 #include <drm_fourcc.h>
 
-#ifdef HAVE_CAIRO
+#if HAVE_CAIRO
 #include <cairo.h>
 #include <math.h>
 #endif
@@ -546,10 +542,9 @@
 static void make_pwetty(void *data, unsigned int width, unsigned int height,
 			unsigned int stride, uint32_t format)
 {
-#ifdef HAVE_CAIRO
+#if HAVE_CAIRO
 	cairo_surface_t *surface;
 	cairo_t *cr;
-	int x, y;
 	cairo_format_t cairo_format;
 
 	/* we can ignore the order of R,G,B channels */
@@ -576,8 +571,8 @@
 	cairo_surface_destroy(surface);
 
 	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
-	for (x = 0; x < width; x += 250)
-		for (y = 0; y < height; y += 250) {
+	for (unsigned x = 0; x < width; x += 250)
+		for (unsigned y = 0; y < height; y += 250) {
 			char buf[64];
 
 			cairo_move_to(cr, x, y - 20);
@@ -824,8 +819,8 @@
 	}
 }
 
-static void fill_plain(const struct util_format_info *info, void *planes[3],
-		       unsigned int width, unsigned int height,
+static void fill_plain(void *planes[3],
+		       unsigned int height,
 		       unsigned int stride)
 {
 	memset(planes[0], 0x77, stride * height);
@@ -861,7 +856,7 @@
 		return fill_smpte(info, planes, width, height, stride);
 
 	case UTIL_PATTERN_PLAIN:
-		return fill_plain(info, planes, width, height, stride);
+		return fill_plain(planes, height, stride);
 
 	default:
 		printf("Error: unsupported test pattern %u.\n", pattern);
diff --git a/tests/vbltest/meson.build b/tests/vbltest/meson.build
new file mode 100644
index 0000000..ae52ab8
--- /dev/null
+++ b/tests/vbltest/meson.build
@@ -0,0 +1,28 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# 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 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.
+
+vbltest = executable(
+  'vbltest',
+  files('vbltest.c'),
+  c_args : warn_c_args,
+  include_directories : [inc_root, inc_tests, inc_drm],
+  link_with : [libdrm, libutil],
+  install : with_install_tests,
+)
diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c
index 3f6b803..48708d2 100644
--- a/tests/vbltest/vbltest.c
+++ b/tests/vbltest/vbltest.c
@@ -24,10 +24,6 @@
  * IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/vc4/meson.build b/vc4/meson.build
new file mode 100644
index 0000000..0136987
--- /dev/null
+++ b/vc4/meson.build
@@ -0,0 +1,28 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+install_headers('vc4_packet.h', 'vc4_qpu_defines.h', subdir : 'libdrm')
+
+pkg.generate(
+  name : 'libdrm_vc4',
+  version : meson.project_version(),
+  requires_private : 'libdrm',
+  description : 'Userspace interface to vc4 kernel DRM services',
+)
diff --git a/xf86atomic.h b/xf86atomic.h
index 922b37d..2d733bd 100644
--- a/xf86atomic.h
+++ b/xf86atomic.h
@@ -34,10 +34,6 @@
 #ifndef LIBDRM_ATOMICS_H
 #define LIBDRM_ATOMICS_H
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #if HAVE_LIBDRM_ATOMIC_PRIMITIVES
 
 #define HAS_ATOMIC_OPS 1
@@ -101,7 +97,7 @@
 
 #endif
 
-#if ! HAS_ATOMIC_OPS
+#if !defined(HAS_ATOMIC_OPS)
 #error libdrm requires atomic operations, please define them for your CPU/compiler.
 #endif
 
diff --git a/xf86drm.c b/xf86drm.c
index 82fb0e2..390e1eb 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -31,9 +31,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
@@ -293,7 +290,7 @@
  * If any other failure happened then it will output error mesage using
  * drmMsg() call.
  */
-#if !defined(UDEV)
+#if !UDEV
 static int chown_check_return(const char *path, uid_t owner, gid_t group)
 {
         int rv;
@@ -332,7 +329,7 @@
     int             fd;
     mode_t          devmode = DRM_DEV_MODE, serv_mode;
     gid_t           serv_group;
-#if !defined(UDEV)
+#if !UDEV
     int             isroot  = !geteuid();
     uid_t           user    = DRM_DEV_UID;
     gid_t           group   = DRM_DEV_GID;
@@ -361,7 +358,7 @@
         devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
     }
 
-#if !defined(UDEV)
+#if !UDEV
     if (stat(DRM_DIR_NAME, &st)) {
         if (!isroot)
             return DRM_ERR_NOT_ROOT;
@@ -414,7 +411,7 @@
     if (fd >= 0)
         return fd;
 
-#if !defined(UDEV)
+#if !UDEV
     /* Check if the device node is not what we expect it to be, and recreate it
      * and try again if so.
      */
@@ -866,8 +863,6 @@
     drmVersionPtr retval;
     drm_version_t *version = drmMalloc(sizeof(*version));
 
-    memclear(*version);
-
     if (drmIoctl(fd, DRM_IOCTL_VERSION, version)) {
         drmFreeKernelVersion(version);
         return NULL;
@@ -994,8 +989,10 @@
     if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
         return NULL;
     u.unique = drmMalloc(u.unique_len + 1);
-    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
+    if (drmIoctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) {
+        drmFree(u.unique);
         return NULL;
+    }
     u.unique[u.unique_len] = '\0';
 
     return u.unique;
@@ -1523,14 +1520,12 @@
 
     if (!(list   = drmMalloc(res.count * sizeof(*list))))
         return NULL;
-    if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
-        drmFree(list);
-        return NULL;
-    }
+    if (!(retval = drmMalloc(res.count * sizeof(*retval))))
+        goto err_free_list;
 
     res.contexts = list;
     if (drmIoctl(fd, DRM_IOCTL_RES_CTX, &res))
-        return NULL;
+        goto err_free_context;
 
     for (i = 0; i < res.count; i++)
         retval[i] = list[i].handle;
@@ -1538,6 +1533,12 @@
 
     *count = res.count;
     return retval;
+
+err_free_list:
+    drmFree(list);
+err_free_context:
+    drmFree(retval);
+    return NULL;
 }
 
 void drmFreeReservedContextList(drm_context_t *pt)
@@ -1691,6 +1692,43 @@
     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.
  *
@@ -2781,12 +2819,11 @@
 {
 #ifdef __linux__
     DIR *sysdir;
-    struct dirent *pent, *ent;
+    struct dirent *ent;
     struct stat sbuf;
     const char *name = drmGetMinorName(type);
     int len;
     char dev_name[64], buf[64];
-    long name_max;
     int maj, min;
 
     if (!name)
@@ -2809,30 +2846,16 @@
     if (!sysdir)
         return NULL;
 
-    name_max = fpathconf(dirfd(sysdir), _PC_NAME_MAX);
-    if (name_max == -1)
-        goto out_close_dir;
-
-    pent = malloc(offsetof(struct dirent, d_name) + name_max + 1);
-    if (pent == NULL)
-         goto out_close_dir;
-
-    while (readdir_r(sysdir, pent, &ent) == 0 && ent != NULL) {
+    while ((ent = readdir(sysdir))) {
         if (strncmp(ent->d_name, name, len) == 0) {
             snprintf(dev_name, sizeof(dev_name), DRM_DIR_NAME "/%s",
                  ent->d_name);
 
-            free(pent);
             closedir(sysdir);
-
             return strdup(dev_name);
         }
     }
-
-    free(pent);
-
-out_close_dir:
-    closedir(sysdir);
+    return NULL;
 #else
     struct stat sbuf;
     char buf[PATH_MAX + 1];
@@ -2873,7 +2896,6 @@
 
     return strdup(buf);
 #endif
-    return NULL;
 }
 
 char *drmGetPrimaryDeviceNameFromFd(int fd)
@@ -3023,32 +3045,32 @@
 #endif
 }
 
-static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
+int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b)
 {
     if (a == NULL || b == NULL)
-        return -1;
+        return 0;
 
     if (a->bustype != b->bustype)
-        return -1;
+        return 0;
 
     switch (a->bustype) {
     case DRM_BUS_PCI:
-        return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
+        return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo)) == 0;
 
     case DRM_BUS_USB:
-        return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo));
+        return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo)) == 0;
 
     case DRM_BUS_PLATFORM:
-        return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo));
+        return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo)) == 0;
 
     case DRM_BUS_HOST1X:
-        return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo));
+        return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0;
 
     default:
         break;
     }
 
-    return -1;
+    return 0;
 }
 
 static int drmGetNodeType(const char *name)
@@ -3663,7 +3685,7 @@
 
     for (i = 0; i < count; i++) {
         for (j = i + 1; j < count; j++) {
-            if (drmCompareBusInfo(local_devices[i], local_devices[j]) == 0) {
+            if (drmDevicesEqual(local_devices[i], local_devices[j])) {
                 local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
                 node_type = log2(local_devices[j]->available_nodes);
                 memcpy(local_devices[i]->nodes[node_type],
@@ -3985,7 +4007,7 @@
             ret = drmProcessUsbDevice(&device, node, node_type, maj, min,
                                       devices != NULL, flags);
             if (ret)
-                goto free_devices;
+                continue;
 
             break;
 
@@ -3993,7 +4015,7 @@
             ret = drmProcessPlatformDevice(&device, node, node_type, maj, min,
                                            devices != NULL, flags);
             if (ret)
-                goto free_devices;
+                continue;
 
             break;
 
@@ -4001,7 +4023,7 @@
             ret = drmProcessHost1xDevice(&device, node, node_type, maj, min,
                                          devices != NULL, flags);
             if (ret)
-                goto free_devices;
+                continue;
 
             break;
 
@@ -4140,3 +4162,132 @@
     return strdup(node);
 #endif
 }
+
+int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle)
+{
+    struct drm_syncobj_create args;
+    int ret;
+
+    memclear(args);
+    args.flags = flags;
+    args.handle = 0;
+    ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args);
+    if (ret)
+        return ret;
+    *handle = args.handle;
+    return 0;
+}
+
+int drmSyncobjDestroy(int fd, uint32_t handle)
+{
+    struct drm_syncobj_destroy args;
+
+    memclear(args);
+    args.handle = handle;
+    return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args);
+}
+
+int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd)
+{
+    struct drm_syncobj_handle args;
+    int ret;
+
+    memclear(args);
+    args.fd = -1;
+    args.handle = handle;
+    ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
+    if (ret)
+        return ret;
+    *obj_fd = args.fd;
+    return 0;
+}
+
+int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle)
+{
+    struct drm_syncobj_handle args;
+    int ret;
+
+    memclear(args);
+    args.fd = obj_fd;
+    args.handle = 0;
+    ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
+    if (ret)
+        return ret;
+    *handle = args.handle;
+    return 0;
+}
+
+int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd)
+{
+    struct drm_syncobj_handle args;
+
+    memclear(args);
+    args.fd = sync_file_fd;
+    args.handle = handle;
+    args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE;
+    return drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
+}
+
+int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd)
+{
+    struct drm_syncobj_handle args;
+    int ret;
+
+    memclear(args);
+    args.fd = -1;
+    args.handle = handle;
+    args.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE;
+    ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
+    if (ret)
+        return ret;
+    *sync_file_fd = args.fd;
+    return 0;
+}
+
+int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles,
+                   int64_t timeout_nsec, unsigned flags,
+                   uint32_t *first_signaled)
+{
+    struct drm_syncobj_wait args;
+    int ret;
+
+    memclear(args);
+    args.handles = (uintptr_t)handles;
+    args.timeout_nsec = timeout_nsec;
+    args.count_handles = num_handles;
+    args.flags = flags;
+
+    ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &args);
+    if (ret < 0)
+        return -errno;
+
+    if (first_signaled)
+        *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 0d92701..7773d71 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -636,6 +636,12 @@
 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 int drmSetMaster(int fd);
 extern int drmDropMaster(int fd);
 
-#define DRM_EVENT_CONTEXT_VERSION 2
+#define DRM_EVENT_CONTEXT_VERSION 4
 
 typedef struct _drmEventContext {
 
@@ -748,6 +754,17 @@
 				  unsigned int tv_usec,
 				  void *user_data);
 
+	void (*page_flip_handler2)(int fd,
+				   unsigned int sequence,
+				   unsigned int tv_sec,
+				   unsigned int tv_usec,
+				   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);
@@ -844,6 +861,21 @@
 extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device);
 extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices);
 
+extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b);
+
+extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle);
+extern int drmSyncobjDestroy(int fd, uint32_t handle);
+extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd);
+extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle);
+
+extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd);
+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)
 }
 #endif
diff --git a/xf86drmHash.c b/xf86drmHash.c
index f287e61..b2fa414 100644
--- a/xf86drmHash.c
+++ b/xf86drmHash.c
@@ -98,9 +98,6 @@
     }
 
     hash %= HASH_SIZE;
-#if DEBUG
-    printf( "Hash(%lu) = %lu\n", key, hash);
-#endif
     return hash;
 }
 
@@ -201,9 +198,6 @@
     bucket->value        = value;
     bucket->next         = table->buckets[hash];
     table->buckets[hash] = bucket;
-#if DEBUG
-    printf("Inserted %lu at %lu/%p\n", key, hash, bucket);
-#endif
     return 0;			/* Added to table */
 }
 
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 2876b42..b0ec609 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -38,10 +38,6 @@
  * platforms find which headers to include to get uint32_t
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <limits.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -271,9 +267,9 @@
 }
 
 int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height,
-                               uint32_t pixel_format, uint32_t bo_handles[4],
-                               uint32_t pitches[4], uint32_t offsets[4],
-                               uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)
+                               uint32_t pixel_format, const uint32_t bo_handles[4],
+                               const uint32_t pitches[4], const uint32_t offsets[4],
+                               const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags)
 {
 	struct drm_mode_fb_cmd2 f;
 	int ret;
@@ -297,8 +293,8 @@
 }
 
 int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
-                  uint32_t pixel_format, uint32_t bo_handles[4],
-                  uint32_t pitches[4], uint32_t offsets[4],
+                  uint32_t pixel_format, const uint32_t bo_handles[4],
+                  const uint32_t pitches[4], const uint32_t offsets[4],
                   uint32_t *buf_id, uint32_t flags)
 {
 	return drmModeAddFB2WithModifiers(fd, width, height,
@@ -831,8 +827,7 @@
 	}
 #elif defined(__DragonFly__)
 	return 0;
-#endif
-#ifdef __OpenBSD__
+#elif defined(__OpenBSD__)
 	int	fd;
 	struct drm_mode_card_res res;
 	drmModeResPtr r = 0;
@@ -889,6 +884,8 @@
 	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
 	 * complete events. */
@@ -915,15 +912,30 @@
 					      U642VOID (vblank->user_data));
 			break;
 		case DRM_EVENT_FLIP_COMPLETE:
-			if (evctx->version < 2 ||
-			    evctx->page_flip_handler == NULL)
-				break;
 			vblank = (struct drm_event_vblank *) e;
-			evctx->page_flip_handler(fd,
-						 vblank->sequence,
-						 vblank->tv_sec,
-						 vblank->tv_usec,
-						 U642VOID (vblank->user_data));
+			user_data = U642VOID (vblank->user_data);
+
+			if (evctx->version >= 3 && evctx->page_flip_handler2)
+				evctx->page_flip_handler2(fd,
+							 vblank->sequence,
+							 vblank->tv_sec,
+							 vblank->tv_usec,
+							 vblank->crtc_id,
+							 user_data);
+			else if (evctx->version >= 2 && evctx->page_flip_handler)
+				evctx->page_flip_handler(fd,
+							 vblank->sequence,
+							 vblank->tv_sec,
+							 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;
@@ -1188,275 +1200,6 @@
 	return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop);
 }
 
-typedef struct _drmModePropertySetItem drmModePropertySetItem, *drmModePropertySetItemPtr;
-
-struct _drmModePropertySetItem {
-	uint32_t object_id;
-	uint32_t property_id;
-	bool is_blob;
-	uint64_t value;
-	void *blob;
-	drmModePropertySetItemPtr next;
-};
-
-struct _drmModePropertySet {
-	unsigned int count_objs;
-	unsigned int count_props;
-	unsigned int count_blobs;
-	drmModePropertySetItem list;
-};
-
-drmModePropertySetPtr drmModePropertySetAlloc(void)
-{
-	drmModePropertySetPtr set;
-
-	set = drmMalloc(sizeof *set);
-	if (!set)
-		return NULL;
-
-	set->list.next = NULL;
-	set->count_props = 0;
-	set->count_objs = 0;
-
-	return set;
-}
-
-int drmModePropertySetAdd(drmModePropertySetPtr set,
-			  uint32_t object_id,
-			  uint32_t property_id,
-			  uint64_t value)
-{
-	drmModePropertySetItemPtr prev = &set->list;
-	bool new_obj = false;
-
-	/* keep it sorted by object_id and property_id */
-	while (prev->next) {
-		if (prev->next->object_id > object_id)
-			break;
-
-		if (prev->next->object_id == object_id &&
-		    prev->next->property_id >= property_id)
-			break;
-
-		prev = prev->next;
-	}
-
-	if ((prev == &set->list || prev->object_id != object_id) &&
-	    (!prev->next || prev->next->object_id != object_id))
-		new_obj = true;
-
-	/* replace or add? */
-	if (prev->next &&
-	    prev->next->object_id == object_id &&
-	    prev->next->property_id == property_id) {
-		drmModePropertySetItemPtr item = prev->next;
-
-		if (item->is_blob)
-			return -EINVAL;
-
-		item->value = value;
-	} else {
-		drmModePropertySetItemPtr item;
-
-		item = drmMalloc(sizeof *item);
-		if (!item)
-			return -1;
-
-		item->object_id = object_id;
-		item->property_id = property_id;
-		item->value = value;
-		item->is_blob = false;
-		item->blob = NULL;
-
-		item->next = prev->next;
-		prev->next = item;
-
-		set->count_props++;
-	}
-
-	if (new_obj)
-		set->count_objs++;
-
-	return 0;
-}
-
-int drmModePropertySetAddBlob(drmModePropertySetPtr set,
-			      uint32_t object_id,
-			      uint32_t property_id,
-			      uint64_t length,
-			      void *data)
-{
-	drmModePropertySetItemPtr prev = &set->list;
-	bool new_obj = false;
-
-	/* keep it sorted by object_id and property_id */
-	while (prev->next) {
-		if (prev->next->object_id > object_id)
-			break;
-
-		if (prev->next->object_id == object_id &&
-		    prev->next->property_id >= property_id)
-			break;
-
-		prev = prev->next;
-	}
-
-	if ((prev == &set->list || prev->object_id != object_id) &&
-	    (!prev->next || prev->next->object_id != object_id))
-		new_obj = true;
-
-	/* replace or add? */
-	if (prev->next &&
-	    prev->next->object_id == object_id &&
-	    prev->next->property_id == property_id) {
-		drmModePropertySetItemPtr item = prev->next;
-
-		if (!item->is_blob)
-			return -EINVAL;
-
-		item->value = length;
-		item->blob = data;
-	} else {
-		drmModePropertySetItemPtr item;
-
-		item = drmMalloc(sizeof *item);
-		if (!item)
-			return -1;
-
-		item->object_id = object_id;
-		item->property_id = property_id;
-		item->is_blob = true;
-		item->value = length;
-		item->blob = data;
-
-		item->next = prev->next;
-		prev->next = item;
-
-		set->count_props++;
-		set->count_blobs++;
-	}
-
-	if (new_obj)
-		set->count_objs++;
-
-	return 0;
-}
-
-void drmModePropertySetFree(drmModePropertySetPtr set)
-{
-	drmModePropertySetItemPtr item;
-
-	if (!set)
-		return;
-
-	item = set->list.next;
-
-	while (item) {
-		drmModePropertySetItemPtr next = item->next;
-
-		drmFree(item);
-
-		item = next;
-	}
-
-	drmFree(set);
-}
-
-int drmModePropertySetCommit(int fd, uint32_t flags, void *user_data,
-			     drmModePropertySetPtr set)
-{
-	drmModePropertySetItemPtr item;
-	uint32_t *objs_ptr = NULL;
-	uint32_t *count_props_ptr = NULL;
-	uint32_t *props_ptr = NULL;
-	uint64_t *prop_values_ptr = NULL;
-	uint64_t *blob_values_ptr = NULL;
-	struct drm_mode_atomic atomic = { 0 };
-	unsigned int obj_idx = 0;
-	unsigned int prop_idx = 0;
-	unsigned int blob_idx = 0;
-	int ret = -1;
-
-	if (!set)
-		return -1;
-
-	objs_ptr = drmMalloc(set->count_objs * sizeof objs_ptr[0]);
-	if (!objs_ptr) {
-		errno = ENOMEM;
-		goto out;
-	}
-
-	count_props_ptr = drmMalloc(set->count_objs * sizeof count_props_ptr[0]);
-	if (!count_props_ptr) {
-		errno = ENOMEM;
-		goto out;
-	}
-
-	props_ptr = drmMalloc(set->count_props * sizeof props_ptr[0]);
-	if (!props_ptr) {
-		errno = ENOMEM;
-		goto out;
-	}
-
-	prop_values_ptr = drmMalloc(set->count_props * sizeof prop_values_ptr[0]);
-	if (!prop_values_ptr) {
-		errno = ENOMEM;
-		goto out;
-	}
-
-	blob_values_ptr = drmMalloc(set->count_blobs * sizeof blob_values_ptr[0]);
-	if (!blob_values_ptr) {
-		errno = ENOMEM;
-		goto out;
-	}
-
-	item = set->list.next;
-
-	while (item) {
-		int count_props = 0;
-		drmModePropertySetItemPtr next = item;
-
-		objs_ptr[obj_idx] = item->object_id;
-
-		while (next && next->object_id == item->object_id) {
-			props_ptr[prop_idx] = next->property_id;
-			prop_values_ptr[prop_idx] = next->value;
-			prop_idx++;
-
-			if (next->is_blob)
-				blob_values_ptr[blob_idx++] = VOID2U64(next->blob);
-
-			count_props++;
-
-			next = next->next;
-		}
-
-		count_props_ptr[obj_idx++] = count_props;
-
-		item = next;
-	}
-
-	atomic.count_objs = set->count_objs;
-	atomic.flags = flags;
-	atomic.objs_ptr = VOID2U64(objs_ptr);
-	atomic.count_props_ptr = VOID2U64(count_props_ptr);
-	atomic.props_ptr = VOID2U64(props_ptr);
-	atomic.prop_values_ptr = VOID2U64(prop_values_ptr);
-// TODO:
-//	atomic.blob_values_ptr = VOID2U64(blob_values_ptr);
-	atomic.user_data = VOID2U64(user_data);
-
-	ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);
-
-out:
-	drmFree(objs_ptr);
-	drmFree(count_props_ptr);
-	drmFree(props_ptr);
-	drmFree(prop_values_ptr);
-
-	return ret;
-}
-
 typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr;
 
 struct _drmModeAtomicReqItem {
@@ -1565,6 +1308,9 @@
 	if (!req)
 		return -EINVAL;
 
+	if (object_id == 0 || property_id == 0)
+		return -EINVAL;
+
 	if (req->cursor >= req->size_items) {
 		const uint32_t item_size_inc = getpagesize() / sizeof(*req->items);
 		drmModeAtomicReqItemPtr new;
@@ -1747,3 +1493,92 @@
 	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 9d73be9..3cd27ae 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -369,15 +369,16 @@
 			uint32_t *buf_id);
 /* ...with a specific pixel format */
 extern int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
-			 uint32_t pixel_format, uint32_t bo_handles[4],
-			 uint32_t pitches[4], uint32_t offsets[4],
+			 uint32_t pixel_format, const uint32_t bo_handles[4],
+			 const uint32_t pitches[4], const uint32_t offsets[4],
 			 uint32_t *buf_id, uint32_t flags);
 
 /* ...with format modifiers */
 int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height,
-			       uint32_t pixel_format, uint32_t bo_handles[4],
-			       uint32_t pitches[4], uint32_t offsets[4],
-			       uint64_t modifier[4], uint32_t *buf_id, uint32_t flags);
+			       uint32_t pixel_format, const uint32_t bo_handles[4],
+			       const uint32_t pitches[4], const uint32_t offsets[4],
+			       const uint64_t modifier[4], uint32_t *buf_id,
+				   uint32_t flags);
 
 /**
  * Destroies the given framebuffer.
@@ -498,25 +499,6 @@
 				    uint64_t value);
 
 
-typedef struct _drmModePropertySet drmModePropertySet, *drmModePropertySetPtr;
-
-extern drmModePropertySetPtr drmModePropertySetAlloc(void);
-
-extern int drmModePropertySetAdd(drmModePropertySetPtr set,
-				 uint32_t object_id,
-				 uint32_t property_id,
-				 uint64_t value);
-extern int drmModePropertySetAddBlob(drmModePropertySetPtr set,
-				     uint32_t object_id,
-				     uint32_t property_id,
-				     uint64_t length,
-				     void *blob);
-
-extern int drmModePropertySetCommit(int fd, uint32_t flags,
-				    void *user_data, drmModePropertySetPtr set);
-
-extern void drmModePropertySetFree(drmModePropertySetPtr set);
-
 typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr;
 
 extern drmModeAtomicReqPtr drmModeAtomicAlloc(void);
@@ -539,6 +521,28 @@
 				     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)
 }