.gitignore                          |    3 
 CleanSpec.mk                        |    1 
 Makefile.am                         |    3 
 amdgpu/amdgpu_bo.c                  |   11 
 amdgpu/amdgpu_cs.c                  |   14 
 amdgpu/amdgpu_vamgr.c               |    8 
 configure.ac                        |    8 
 exynos/exynos-symbol-check          |    3 
 exynos/exynos_drm.c                 |   76 ++
 exynos/exynos_drm.h                 |   12 
 exynos/exynos_drmif.h               |   26 
 exynos/exynos_fimg2d.c              |  548 +++++++++++++++-----
 exynos/exynos_fimg2d.h              |   18 
 exynos/libdrm_exynos.pc.in          |    2 
 freedreno/freedreno_bo.c            |   26 
 freedreno/freedreno_priv.h          |    1 
 freedreno/kgsl/kgsl_bo.c            |    1 
 freedreno/msm/msm_bo.c              |    1 
 freedreno/msm/msm_ringbuffer.c      |    4 
 include/drm/drm_fourcc.h            |    2 
 include/drm/i915_drm.h              |   59 +-
 include/drm/nouveau_drm.h           |    1 
 include/drm/virtgpu_drm.h           |  167 ++++++
 intel/intel-symbol-check            |    2 
 intel/intel_bufmgr.c                |   20 
 intel/intel_bufmgr.h                |    2 
 intel/intel_bufmgr_fake.c           |    1 
 intel/intel_bufmgr_gem.c            |  250 ++++++++-
 intel/intel_bufmgr_priv.h           |   21 
 intel/intel_chipset.h               |   58 +-
 nouveau/Makefile.am                 |   11 
 nouveau/abi16.c                     |  162 +++++-
 nouveau/libdrm_nouveau.pc.in        |    2 
 nouveau/nouveau-symbol-check        |    8 
 nouveau/nouveau.c                   |  574 +++++++++++++++------
 nouveau/nouveau.h                   |  210 ++++---
 nouveau/nvif/cl0080.h               |   45 +
 nouveau/nvif/cl9097.h               |   44 +
 nouveau/nvif/class.h                |  141 +++++
 nouveau/nvif/if0002.h               |   38 +
 nouveau/nvif/if0003.h               |   33 +
 nouveau/nvif/ioctl.h                |  132 ++++
 nouveau/nvif/unpack.h               |   28 +
 nouveau/private.h                   |    8 
 nouveau/pushbuf.c                   |    7 
 radeon/radeon_surface.c             |   17 
 tests/Makefile.am                   |    3 
 tests/drmdevice.c                   |  112 ++++
 tests/exynos/Makefile.am            |   26 
 tests/exynos/exynos_fimg2d_event.c  |  326 ++++++++++++
 tests/exynos/exynos_fimg2d_perf.c   |  327 ++++++++++++
 tests/exynos/exynos_fimg2d_test.c   |  134 ++++-
 tests/kms/Makefile.am               |   36 +
 tests/kms/kms-steal-crtc.c          |  161 ++++++
 tests/kms/kms-universal-planes.c    |  358 +++++++++++++
 tests/kms/libkms-test-crtc.c        |   47 +
 tests/kms/libkms-test-device.c      |  218 ++++++++
 tests/kms/libkms-test-framebuffer.c |  157 +++++
 tests/kms/libkms-test-plane.c       |  139 +++++
 tests/kms/libkms-test-screen.c      |   92 +++
 tests/kms/libkms-test.h             |  120 ++++
 tests/modeprint/Makefile.am         |    1 
 tests/modeprint/modeprint.c         |    2 
 tests/modetest/Android.mk           |    1 
 tests/modetest/Makefile.am          |    8 
 tests/modetest/buffers.c            |  961 ------------------------------------
 tests/modetest/buffers.h            |   12 
 tests/modetest/cursor.c             |    4 
 tests/modetest/modetest.c           |  120 ----
 tests/proptest/Android.mk           |   13 
 tests/proptest/Makefile.am          |   10 
 tests/proptest/Makefile.sources     |    2 
 tests/proptest/proptest.c           |  104 +--
 tests/util/Android.mk               |   39 +
 tests/util/Makefile.am              |   13 
 tests/util/Makefile.sources         |    8 
 tests/util/common.h                 |   33 +
 tests/util/format.c                 |  120 ++++
 tests/util/format.h                 |   65 ++
 tests/util/kms.c                    |  177 ++++++
 tests/util/kms.h                    |   35 +
 tests/util/pattern.c                |  870 ++++++++++++++++++++++++++++++++
 tests/util/pattern.h                |   39 +
 tests/vbltest/Makefile.am           |    4 
 tests/vbltest/vbltest.c             |   55 --
 util_math.h                         |    1 
 xf86atomic.h                        |    2 
 xf86drm.c                           |  508 +++++++++++--------
 xf86drm.h                           |    3 
 xf86drmMode.c                       |   17 
 90 files changed, 6370 insertions(+), 1922 deletions(-)

New commits:
commit b38a4b2326c1be5702f5cb73a53c0ed74c12d510
Author: Michał Winiarski <[email protected]>
Date:   Tue Dec 15 16:28:55 2015 +0100

    intel: Restore formatting of offsets in debug statements
    
    Using lower_32_bits and upper_32_bits macros was accidentally dropped in:
    
        commit 8b4d57e7b75cb0bd01d11ad7f597909034a316aa
        Author: Michał Winiarski <[email protected]>
        Date:   Wed Sep 9 16:07:10 2015 +0200
    
        intel: Add support for softpin
    
    Let's restore previous, more readable format.
    
    Signed-off-by: Michał Winiarski <[email protected]>
    Reviewed-by: Kenneth Graunke <[email protected]>

diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 265516f..dc28200 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -438,16 +438,18 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem 
*bufmgr_gem)
                        drm_intel_bo_gem *target_gem =
                            (drm_intel_bo_gem *) target_bo;
 
-                       DBG("%2d: %d %s(%s)@0x%016llx -> "
-                           "%d (%s)@0x%016llx + 0x%08x\n",
+                       DBG("%2d: %d %s(%s)@0x%08x %08x -> "
+                           "%d (%s)@0x%08x %08x + 0x%08x\n",
                            i,
                            bo_gem->gem_handle,
                            bo_gem->is_softpin ? "*" : "",
                            bo_gem->name,
-                           (unsigned long long) bo_gem->relocs[j].offset,
+                           upper_32_bits(bo_gem->relocs[j].offset),
+                           lower_32_bits(bo_gem->relocs[j].offset),
                            target_gem->gem_handle,
                            target_gem->name,
-                           (unsigned long long) target_bo->offset64,
+                           upper_32_bits(target_bo->offset64),
+                           lower_32_bits(target_bo->offset64),
                            bo_gem->relocs[j].delta);
                }
 
@@ -456,14 +458,15 @@ drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem 
*bufmgr_gem)
                        drm_intel_bo_gem *target_gem =
                            (drm_intel_bo_gem *) target_bo;
                        DBG("%2d: %d %s(%s) -> "
-                           "%d *(%s)@0x%016lx\n",
+                           "%d *(%s)@0x%08x %08x\n",
                            i,
                            bo_gem->gem_handle,
                            bo_gem->is_softpin ? "*" : "",
                            bo_gem->name,
                            target_gem->gem_handle,
                            target_gem->name,
-                           target_bo->offset64);
+                           upper_32_bits(target_bo->offset64),
+                           lower_32_bits(target_bo->offset64));
                }
        }
 }
@@ -2242,10 +2245,12 @@ drm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem 
*bufmgr_gem)
                         * has relocated our object... Indicating a programming 
error
                         */
                        assert(!bo_gem->is_softpin);
-                       DBG("BO %d (%s) migrated: 0x%016llx -> 0x%016llx\n",
+                       DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
                            bo_gem->gem_handle, bo_gem->name,
-                           (unsigned long long) bo->offset64,
-                           (unsigned long long) 
bufmgr_gem->exec2_objects[i].offset);
+                           upper_32_bits(bo->offset64),
+                           lower_32_bits(bo->offset64),
+                           upper_32_bits(bufmgr_gem->exec2_objects[i].offset),
+                           lower_32_bits(bufmgr_gem->exec2_objects[i].offset));
                        bo->offset64 = bufmgr_gem->exec2_objects[i].offset;
                        bo->offset = bufmgr_gem->exec2_objects[i].offset;
                }

commit f49bfd98b35e5794cb60bcc4613050dfa640940c
Author: Ben Skeggs <[email protected]>
Date:   Tue Nov 24 11:57:39 2015 +1000

    Bump version for release
    
    Signed-off-by: Ben Skeggs <[email protected]>
    Tested-by: Samuel Pitoiset <[email protected]>
    Reviewed-by: Emil Velikov <[email protected]>

diff --git a/configure.ac b/configure.ac
index 0c66dfc..c8c4ace 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
 
 AC_PREREQ([2.63])
 AC_INIT([libdrm],
-        [2.4.65],
+        [2.4.66],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
         [libdrm])
 

commit f208f2afdee6222ea8f6692a6ec4381cc999eb05
Author: Ben Skeggs <[email protected]>
Date:   Thu Nov 26 08:24:55 2015 +1000

    nouveau: clean up nouveau.h, noting deprecated members/functions
    
    Signed-off-by: Ben Skeggs <[email protected]>
    Tested-by: Samuel Pitoiset <[email protected]>
    Reviewed-by: Emil Velikov <[email protected]>

diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
index f3cf8f5..335ce77 100644
--- a/nouveau/nouveau.h
+++ b/nouveau/nouveau.h
@@ -4,24 +4,43 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#define NOUVEAU_DEVICE_CLASS       0x80000000
-#define NOUVEAU_FIFO_CHANNEL_CLASS 0x80000001
-#define NOUVEAU_NOTIFIER_CLASS     0x80000002
-#define NOUVEAU_PARENT_CLASS       0xffffffff
+/* Supported class information, provided by the kernel */
+struct nouveau_sclass {
+       int32_t oclass;
+       int minver;
+       int maxver;
+};
 
-struct nouveau_list {
-       struct nouveau_list *prev;
-       struct nouveau_list *next;
+/* Client-provided array describing class versions that are desired.
+ *
+ * These are used to match against the kernel's list of supported classes.
+ */
+struct nouveau_mclass {
+       int32_t oclass;
+       int version;
+       void *data;
 };
 
 struct nouveau_object {
        struct nouveau_object *parent;
        uint64_t handle;
        uint32_t oclass;
-       uint32_t length;
-       void *data;
+       uint32_t length;        /* deprecated */
+       void *data;             /* deprecated */
 };
 
+int nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
+                      uint32_t oclass, void *data, uint32_t length,
+                      struct nouveau_object **);
+void nouveau_object_del(struct nouveau_object **);
+int nouveau_object_mthd(struct nouveau_object *, uint32_t mthd,
+                       void *data, uint32_t size);
+int nouveau_object_sclass_get(struct nouveau_object *,
+                             struct nouveau_sclass **);
+void nouveau_object_sclass_put(struct nouveau_sclass **);
+int nouveau_object_mclass(struct nouveau_object *,
+                         const struct nouveau_mclass *);
+
 struct nouveau_drm {
        struct nouveau_object client;
        int fd;
@@ -40,81 +59,11 @@ nouveau_drm(struct nouveau_object *obj)
 int nouveau_drm_new(int fd, struct nouveau_drm **);
 void nouveau_drm_del(struct nouveau_drm **);
 
-struct nouveau_fifo {
-       struct nouveau_object *object;
-       uint32_t channel;
-       uint32_t pushbuf;
-       uint64_t unused1[3];
-};
-
-struct nv04_fifo {
-       struct nouveau_fifo base;
-       uint32_t vram;
-       uint32_t gart;
-       uint32_t notify;
-};
-
-struct nvc0_fifo {
-       struct nouveau_fifo base;
-       uint32_t notify;
-};
-
-#define NVE0_FIFO_ENGINE_GR  0x00000001
-#define NVE0_FIFO_ENGINE_VP  0x00000002
-#define NVE0_FIFO_ENGINE_PPP 0x00000004
-#define NVE0_FIFO_ENGINE_BSP 0x00000008
-#define NVE0_FIFO_ENGINE_CE0 0x00000010
-#define NVE0_FIFO_ENGINE_CE1 0x00000020
-#define NVE0_FIFO_ENGINE_ENC 0x00000040
-
-struct nve0_fifo {
-       struct {
-               struct nouveau_fifo base;
-               uint32_t notify;
-       };
-       uint32_t engine;
-};
-
-struct nv04_notify {
-       struct nouveau_object *object;
-       uint32_t offset;
-       uint32_t length;
-};
-
-/* Supported class information, provided by the kernel */
-struct nouveau_sclass {
-       int32_t oclass;
-       int minver;
-       int maxver;
-};
-
-/* Client-provided array describing class versions that are desired.
- *
- * These are used to match against the kernel's list of supported classes.
- */
-struct nouveau_mclass {
-       int32_t oclass; /* 0 == EOL */
-       int version;
-       void *data;
-};
-
-int  nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
-                       uint32_t oclass, void *data, uint32_t length,
-                       struct nouveau_object **);
-void nouveau_object_del(struct nouveau_object **);
-int  nouveau_object_mthd(struct nouveau_object *, uint32_t mthd,
-                        void *data, uint32_t size);
-int  nouveau_object_sclass_get(struct nouveau_object *,
-                              struct nouveau_sclass **);
-void nouveau_object_sclass_put(struct nouveau_sclass **);
-int  nouveau_object_mclass(struct nouveau_object *,
-                          const struct nouveau_mclass *);
-
 struct nouveau_device {
        struct nouveau_object object;
-       int fd;
-       uint32_t lib_version;
-       uint32_t drm_version;
+       int fd;                 /* deprecated */
+       uint32_t lib_version;   /* deprecated */
+       uint32_t drm_version;   /* deprecated */
        uint32_t chipset;
        uint64_t vram_size;
        uint64_t gart_size;
@@ -122,20 +71,23 @@ struct nouveau_device {
        uint64_t gart_limit;
 };
 
-int  nouveau_device_new(struct nouveau_object *parent, int32_t oclass,
-                       void *data, uint32_t size, struct nouveau_device **);
-int  nouveau_device_wrap(int fd, int close, struct nouveau_device **);
-int  nouveau_device_open(const char *busid, struct nouveau_device **);
+int nouveau_device_new(struct nouveau_object *parent, int32_t oclass,
+                      void *data, uint32_t size, struct nouveau_device **);
 void nouveau_device_del(struct nouveau_device **);
-int  nouveau_getparam(struct nouveau_device *, uint64_t param, uint64_t 
*value);
-int  nouveau_setparam(struct nouveau_device *, uint64_t param, uint64_t value);
+
+int nouveau_getparam(struct nouveau_device *, uint64_t param, uint64_t *value);
+int nouveau_setparam(struct nouveau_device *, uint64_t param, uint64_t value);
+
+/* deprecated */
+int nouveau_device_wrap(int fd, int close, struct nouveau_device **);
+int nouveau_device_open(const char *busid, struct nouveau_device **);
 
 struct nouveau_client {
        struct nouveau_device *device;
        int id;
 };
 
-int  nouveau_client_new(struct nouveau_device *, struct nouveau_client **);
+int nouveau_client_new(struct nouveau_device *, struct nouveau_client **);
 void nouveau_client_del(struct nouveau_client **);
 
 union nouveau_bo_config {
@@ -182,22 +134,27 @@ struct nouveau_bo {
        union nouveau_bo_config config;
 };
 
-int  nouveau_bo_new(struct nouveau_device *, uint32_t flags, uint32_t align,
-                   uint64_t size, union nouveau_bo_config *,
+int nouveau_bo_new(struct nouveau_device *, uint32_t flags, uint32_t align,
+                  uint64_t size, union nouveau_bo_config *,
+                  struct nouveau_bo **);
+int nouveau_bo_wrap(struct nouveau_device *, uint32_t handle,
                    struct nouveau_bo **);
-int  nouveau_bo_wrap(struct nouveau_device *, uint32_t handle,
-                    struct nouveau_bo **);
-int  nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
-                        struct nouveau_bo **);
-int  nouveau_bo_name_get(struct nouveau_bo *, uint32_t *name);
+int nouveau_bo_name_ref(struct nouveau_device *v, uint32_t name,
+                       struct nouveau_bo **);
+int nouveau_bo_name_get(struct nouveau_bo *, uint32_t *name);
 void nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
-int  nouveau_bo_map(struct nouveau_bo *, uint32_t access,
+int nouveau_bo_map(struct nouveau_bo *, uint32_t access,
+                  struct nouveau_client *);
+int nouveau_bo_wait(struct nouveau_bo *, uint32_t access,
                    struct nouveau_client *);
-int  nouveau_bo_wait(struct nouveau_bo *, uint32_t access,
-                    struct nouveau_client *);
-int  nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd,
-                                struct nouveau_bo **);
-int  nouveau_bo_set_prime(struct nouveau_bo *bo, int *prime_fd);
+int nouveau_bo_prime_handle_ref(struct nouveau_device *, int prime_fd,
+                               struct nouveau_bo **);
+int nouveau_bo_set_prime(struct nouveau_bo *, int *prime_fd);
+
+struct nouveau_list {
+       struct nouveau_list *prev;
+       struct nouveau_list *next;
+};
 
 struct nouveau_bufref {
        struct nouveau_list thead;
@@ -219,8 +176,8 @@ struct nouveau_bufctx {
        int relocs;
 };
 
-int  nouveau_bufctx_new(struct nouveau_client *, int bins,
-                       struct nouveau_bufctx **);
+int nouveau_bufctx_new(struct nouveau_client *, int bins,
+                      struct nouveau_bufctx **);
 void nouveau_bufctx_del(struct nouveau_bufctx **);
 struct nouveau_bufref *
 nouveau_bufctx_refn(struct nouveau_bufctx *, int bin,
@@ -249,16 +206,16 @@ struct nouveau_pushbuf_refn {
        uint32_t flags;
 };
 
-int  nouveau_pushbuf_new(struct nouveau_client *, struct nouveau_object 
*channel,
-                        int nr, uint32_t size, bool immediate,
-                        struct nouveau_pushbuf **);
+int nouveau_pushbuf_new(struct nouveau_client *, struct nouveau_object *chan,
+                       int nr, uint32_t size, bool immediate,
+                       struct nouveau_pushbuf **);
 void nouveau_pushbuf_del(struct nouveau_pushbuf **);
-int  nouveau_pushbuf_space(struct nouveau_pushbuf *, uint32_t dwords,
-                          uint32_t relocs, uint32_t pushes);
+int nouveau_pushbuf_space(struct nouveau_pushbuf *, uint32_t dwords,
+                         uint32_t relocs, uint32_t pushes);
 void nouveau_pushbuf_data(struct nouveau_pushbuf *, struct nouveau_bo *,
                          uint64_t offset, uint64_t length);
-int  nouveau_pushbuf_refn(struct nouveau_pushbuf *,
-                         struct nouveau_pushbuf_refn *, int nr);
+int nouveau_pushbuf_refn(struct nouveau_pushbuf *,
+                        struct nouveau_pushbuf_refn *, int nr);
 /* Emits a reloc into the push buffer at the current position, you *must*
  * have previously added the referenced buffer to a buffer context, and
  * validated it against the current push buffer.
@@ -266,10 +223,54 @@ int  nouveau_pushbuf_refn(struct nouveau_pushbuf *,
 void nouveau_pushbuf_reloc(struct nouveau_pushbuf *, struct nouveau_bo *,
                           uint32_t data, uint32_t flags,
                           uint32_t vor, uint32_t tor);
-int  nouveau_pushbuf_validate(struct nouveau_pushbuf *);
+int nouveau_pushbuf_validate(struct nouveau_pushbuf *);
 uint32_t nouveau_pushbuf_refd(struct nouveau_pushbuf *, struct nouveau_bo *);
-int  nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object 
*channel);
+int nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object 
*chan);
 struct nouveau_bufctx *
 nouveau_pushbuf_bufctx(struct nouveau_pushbuf *, struct nouveau_bufctx *);
 
+#define NOUVEAU_DEVICE_CLASS       0x80000000
+#define NOUVEAU_FIFO_CHANNEL_CLASS 0x80000001
+#define NOUVEAU_NOTIFIER_CLASS     0x80000002
+
+struct nouveau_fifo {
+       struct nouveau_object *object;
+       uint32_t channel;
+       uint32_t pushbuf;
+       uint64_t unused1[3];
+};
+
+struct nv04_fifo {
+       struct nouveau_fifo base;
+       uint32_t vram;
+       uint32_t gart;
+       uint32_t notify;
+};
+
+struct nvc0_fifo {
+       struct nouveau_fifo base;
+       uint32_t notify;
+};
+
+#define NVE0_FIFO_ENGINE_GR  0x00000001
+#define NVE0_FIFO_ENGINE_VP  0x00000002
+#define NVE0_FIFO_ENGINE_PPP 0x00000004
+#define NVE0_FIFO_ENGINE_BSP 0x00000008
+#define NVE0_FIFO_ENGINE_CE0 0x00000010
+#define NVE0_FIFO_ENGINE_CE1 0x00000020
+#define NVE0_FIFO_ENGINE_ENC 0x00000040
+
+struct nve0_fifo {
+       struct {
+               struct nouveau_fifo base;
+               uint32_t notify;
+       };
+       uint32_t engine;
+};
+
+struct nv04_notify {
+       struct nouveau_object *object;
+       uint32_t offset;
+       uint32_t length;
+};
 #endif

commit 4291eea18fd81ca084935fb09a0e97a6661f4f85
Author: Ben Skeggs <[email protected]>
Date:   Tue Nov 24 13:08:21 2015 +1000

    nouveau: add support for newer kernel interfaces
    
    v2.
    - leave client-provided pointer unmodified on sclass_get() failure
    
    Signed-off-by: Ben Skeggs <[email protected]>
    Tested-by: Samuel Pitoiset <[email protected]>
    Reviewed-by: Emil Velikov <[email protected]>

diff --git a/nouveau/abi16.c b/nouveau/abi16.c
index 46350b1..ee38c0c 100644
--- a/nouveau/abi16.c
+++ b/nouveau/abi16.c
@@ -244,7 +244,8 @@ abi16_object(struct nouveau_object *obj, int 
(**func)(struct nouveau_object *))
        /* nouveau_object::length is (ab)used to determine whether the
         * object is a legacy object (!=0), or a real NVIF object.
         */
-       if ((parent->length != 0 && parent->oclass == NOUVEAU_DEVICE_CLASS)) {
+       if ((parent->length != 0 && parent->oclass == NOUVEAU_DEVICE_CLASS) ||
+           (parent->length == 0 && parent->oclass == NV_DEVICE)) {
                if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) {
                        struct nouveau_device *dev = (void *)parent;
                        if (dev->chipset < 0xc0)
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
index fef338b..e113a8f 100644
--- a/nouveau/nouveau.c
+++ b/nouveau/nouveau.c
@@ -47,6 +47,7 @@
 
 #include "nvif/class.h"
 #include "nvif/cl0080.h"
+#include "nvif/ioctl.h"
 #include "nvif/unpack.h"
 
 #ifdef DEBUG
@@ -63,11 +64,67 @@ debug_init(char *args)
 }
 #endif
 
+static int
+nouveau_object_ioctl(struct nouveau_object *obj, void *data, uint32_t size)
+{
+       struct nouveau_drm *drm = nouveau_drm(obj);
+       union {
+               struct nvif_ioctl_v0 v0;
+       } *args = data;
+       uint32_t argc = size;
+       int ret = -ENOSYS;
+
+       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
+               if (!obj->length) {
+                       if (obj != &drm->client)
+                               args->v0.object = (unsigned long)(void *)obj;
+                       else
+                               args->v0.object = 0;
+                       args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+                       args->v0.route = 0x00;
+               } else {
+                       args->v0.route = 0xff;
+                       args->v0.token = obj->handle;
+               }
+       } else
+               return ret;
+
+       return drmCommandWriteRead(drm->fd, DRM_NOUVEAU_NVIF, args, argc);
+}
+
 int
 nouveau_object_mthd(struct nouveau_object *obj,
                    uint32_t mthd, void *data, uint32_t size)
 {
-       return -ENODEV;
+       struct nouveau_drm *drm = nouveau_drm(obj);
+       struct {
+               struct nvif_ioctl_v0 ioctl;
+               struct nvif_ioctl_mthd_v0 mthd;
+       } *args;
+       uint32_t argc = sizeof(*args) + size;
+       uint8_t stack[128];
+       int ret;
+
+       if (!drm->nvif)
+               return -ENOSYS;
+
+       if (argc > sizeof(stack)) {
+               if (!(args = malloc(argc)))
+                       return -ENOMEM;
+       } else {
+               args = (void *)stack;
+       }
+       args->ioctl.version = 0;
+       args->ioctl.type = NVIF_IOCTL_V0_MTHD;
+       args->mthd.version = 0;
+       args->mthd.method = mthd;
+
+       memcpy(args->mthd.data, data, size);
+       ret = nouveau_object_ioctl(obj, args, argc);
+       memcpy(data, args->mthd.data, size);
+       if (args != (void *)stack)
+               free(args);
+       return ret;
 }
 
 void
@@ -81,7 +138,50 @@ int
 nouveau_object_sclass_get(struct nouveau_object *obj,
                          struct nouveau_sclass **psclass)
 {
-       return abi16_sclass(obj, psclass);
+       struct nouveau_drm *drm = nouveau_drm(obj);
+       struct {
+               struct nvif_ioctl_v0 ioctl;
+               struct nvif_ioctl_sclass_v0 sclass;
+       } *args = NULL;
+       struct nouveau_sclass *sclass;
+       int ret, cnt = 0, i;
+       uint32_t size;
+
+       if (!drm->nvif)
+               return abi16_sclass(obj, psclass);
+
+       while (1) {
+               size = sizeof(*args) + cnt * sizeof(args->sclass.oclass[0]);
+               if (!(args = malloc(size)))
+                       return -ENOMEM;
+               args->ioctl.version = 0;
+               args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
+               args->sclass.version = 0;
+               args->sclass.count = cnt;
+
+               ret = nouveau_object_ioctl(obj, args, size);
+               if (ret == 0 && args->sclass.count <= cnt)
+                       break;
+               cnt = args->sclass.count;
+               free(args);
+               if (ret != 0)
+                       return ret;
+       }
+
+       if ((sclass = calloc(args->sclass.count, sizeof(*sclass)))) {
+               for (i = 0; i < args->sclass.count; i++) {
+                       sclass[i].oclass = args->sclass.oclass[i].oclass;
+                       sclass[i].minver = args->sclass.oclass[i].minver;
+                       sclass[i].maxver = args->sclass.oclass[i].maxver;
+               }
+               *psclass = sclass;
+               ret = args->sclass.count;
+       } else {
+               ret = -ENOMEM;
+       }
+
+       free(args);
+       return ret;
 }
 
 int
@@ -114,12 +214,21 @@ nouveau_object_mclass(struct nouveau_object *obj,
 static void
 nouveau_object_fini(struct nouveau_object *obj)
 {
+       struct {
+               struct nvif_ioctl_v0 ioctl;
+               struct nvif_ioctl_del del;
+       } args = {
+               .ioctl.type = NVIF_IOCTL_V0_DEL,
+       };
+
        if (obj->data) {
                abi16_delete(obj);
                free(obj->data);
                obj->data = NULL;
                return;
        }
+
+       nouveau_object_ioctl(obj, &args, sizeof(args));
 }
 
 static int
@@ -127,6 +236,12 @@ nouveau_object_init(struct nouveau_object *parent, 
uint32_t handle,
                    int32_t oclass, void *data, uint32_t size,
                    struct nouveau_object *obj)
 {
+       struct nouveau_drm *drm = nouveau_drm(parent);
+       struct {
+               struct nvif_ioctl_v0 ioctl;
+               struct nvif_ioctl_new_v0 new;
+       } *args;
+       uint32_t argc = sizeof(*args) + size;
        int (*func)(struct nouveau_object *);
        int ret = -ENOSYS;
 
@@ -136,7 +251,22 @@ nouveau_object_init(struct nouveau_object *parent, 
uint32_t handle,
        obj->length = 0;
        obj->data = NULL;
 
-       abi16_object(obj, &func);
+       if (!abi16_object(obj, &func) && drm->nvif) {
+               if (!(args = malloc(argc)))
+                       return -ENOMEM;
+               args->ioctl.version = 0;
+               args->ioctl.type = NVIF_IOCTL_V0_NEW;
+               args->new.version = 0;
+               args->new.route = NVIF_IOCTL_V0_ROUTE_NVIF;
+               args->new.token = (unsigned long)(void *)obj;
+               args->new.object = (unsigned long)(void *)obj;
+               args->new.handle = handle;
+               args->new.oclass = oclass;
+               memcpy(args->new.data, data, size);
+               ret = nouveau_object_ioctl(parent, args, argc);
+               memcpy(data, args->new.data, size);
+               free(args);
+       } else
        if (func) {
                obj->length = size ? size : sizeof(struct nouveau_object *);
                if (!(obj->data = malloc(obj->length)))
@@ -218,7 +348,7 @@ nouveau_drm_new(int fd, struct nouveau_drm **pdrm)
        drm->version = (ver->version_major << 24) |
                       (ver->version_minor << 8) |
                        ver->version_patchlevel;
-       drm->nvif = false;
+       drm->nvif = (drm->version >= 0x01000301);
        drmFreeVersion(ver);
        return 0;
 }
@@ -238,9 +368,11 @@ int
 nouveau_device_new(struct nouveau_object *parent, int32_t oclass,
                   void *data, uint32_t size, struct nouveau_device **pdev)
 {
+       struct nv_device_info_v0 info = {};
        union {
                struct nv_device_v0 v0;
        } *args = data;
+       uint32_t argc = size;
        struct nouveau_drm *drm = nouveau_drm(parent);
        struct nouveau_device_priv *nvdev;
        struct nouveau_device *dev;
@@ -257,6 +389,22 @@ nouveau_device_new(struct nouveau_object *parent, int32_t 
oclass,
        dev = *pdev = &nvdev->base;
        dev->fd = -1;
 
+       if (drm->nvif) {
+               ret = nouveau_object_init(parent, 0, oclass, args, argc,
+                                         &dev->object);
+               if (ret)
+                       goto done;
+
+               info.version = 0;
+
+               ret = nouveau_object_mthd(&dev->object, NV_DEVICE_V0_INFO,
+                                         &info, sizeof(info));
+               if (ret)
+                       goto done;
+
+               nvdev->base.chipset = info.chipset;
+               nvdev->have_bo_usage = true;
+       } else
        if (args->v0.device == ~0ULL) {
                nvdev->base.object.parent = &drm->client;
                nvdev->base.object.handle = ~0ULL;
@@ -333,8 +481,7 @@ nouveau_device_wrap(int fd, int close, struct 
nouveau_device **pdev)
 
        nvdev = nouveau_device(*pdev);
        nvdev->base.fd = drm->fd;
-       nvdev->base.drm_version = drm->drm_version;
-       nvdev->base.lib_version = drm->lib_version;
+       nvdev->base.drm_version = drm->version;
        nvdev->close = close;
        return 0;
 }

commit 4c92a9d70725ec393899979bbfc21a37684e88d9
Author: Ben Skeggs <[email protected]>
Date:   Tue Nov 24 11:21:05 2015 +1000

    nouveau: add new interface to create a nouveau_device
    
    Signed-off-by: Ben Skeggs <[email protected]>
    Tested-by: Samuel Pitoiset <[email protected]>
    Reviewed-by: Emil Velikov <[email protected]>

diff --git a/nouveau/nouveau-symbol-check b/nouveau/nouveau-symbol-check
index 275b6e7..b265cea 100755
--- a/nouveau/nouveau-symbol-check
+++ b/nouveau/nouveau-symbol-check
@@ -27,6 +27,7 @@ nouveau_bufctx_reset
 nouveau_client_del
 nouveau_client_new
 nouveau_device_del
+nouveau_device_new
 nouveau_device_open
 nouveau_device_open_existing
 nouveau_device_wrap
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
index 56e00ac..fef338b 100644
--- a/nouveau/nouveau.c
+++ b/nouveau/nouveau.c
@@ -45,6 +45,10 @@
 #include "nouveau.h"
 #include "private.h"
 
+#include "nvif/class.h"
+#include "nvif/cl0080.h"
+#include "nvif/unpack.h"
+
 #ifdef DEBUG
 drm_private uint32_t nouveau_debug = 0;
 
@@ -231,75 +235,107 @@ nouveau_device_open_existing(struct nouveau_device 
**pdev, int close, int fd,
 }
 
 int
-nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev)
+nouveau_device_new(struct nouveau_object *parent, int32_t oclass,
+                  void *data, uint32_t size, struct nouveau_device **pdev)
 {
-       struct nouveau_drm *drm;
+       union {
+               struct nv_device_v0 v0;
+       } *args = data;
+       struct nouveau_drm *drm = nouveau_drm(parent);
        struct nouveau_device_priv *nvdev;
        struct nouveau_device *dev;
-       uint64_t chipset, vram, gart, bousage;
-       int ret;
+       uint64_t v;
        char *tmp;
+       int ret = -ENOSYS;
+
+       if (oclass != NV_DEVICE ||
+           nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))
+               return ret;
 
        if (!(nvdev = calloc(1, sizeof(*nvdev))))
                return -ENOMEM;
-       dev = &nvdev->base;
+       dev = *pdev = &nvdev->base;
+       dev->fd = -1;
 
-       ret = pthread_mutex_init(&nvdev->lock, NULL);
-       if (ret) {
-               free(nvdev);
-               return ret;
-       }
-
-       ret = nouveau_drm_new(fd, &drm);
-       if (ret) {
-               nouveau_device_del(&dev);
-               return ret;
-       }
-       drm->nvif = false;
+       if (args->v0.device == ~0ULL) {
+               nvdev->base.object.parent = &drm->client;
+               nvdev->base.object.handle = ~0ULL;
+               nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
+               nvdev->base.object.length = ~0;
 
-       nvdev->base.object.parent = &drm->client;
-       nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
-       nvdev->base.object.length = ~0;
-       nvdev->base.fd = drm->fd;
-       nvdev->base.drm_version = drm->drm_version;
-       nvdev->base.lib_version = drm->lib_version;
+               ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &v);
+               if (ret)
+                       goto done;
+               nvdev->base.chipset = v;
 
-       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &chipset);
-       if (ret == 0)
-       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &vram);
-       if (ret == 0)
-       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &gart);
-       if (ret) {
-               nouveau_device_del(&dev);
-               return ret;
-       }
+               ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &v);
+               if (ret == 0)
+                       nvdev->have_bo_usage = (v != 0);
+       } else
+               return -ENOSYS;
 
-       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &bousage);
-       if (ret == 0)
-               nvdev->have_bo_usage = (bousage != 0);
+       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &v);
+       if (ret)
+               goto done;
+       nvdev->base.vram_size = v;
 
-       nvdev->close = close;
+       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &v);
+       if (ret)
+               goto done;
+       nvdev->base.gart_size = v;
 
        tmp = getenv("NOUVEAU_LIBDRM_VRAM_LIMIT_PERCENT");
        if (tmp)
                nvdev->vram_limit_percent = atoi(tmp);
        else
                nvdev->vram_limit_percent = 80;
+
+       nvdev->base.vram_limit =
+               (nvdev->base.vram_size * nvdev->vram_limit_percent) / 100;
+
        tmp = getenv("NOUVEAU_LIBDRM_GART_LIMIT_PERCENT");
        if (tmp)
                nvdev->gart_limit_percent = atoi(tmp);
        else
                nvdev->gart_limit_percent = 80;
-       DRMINITLISTHEAD(&nvdev->bo_list);
-       nvdev->base.chipset = chipset;
-       nvdev->base.vram_size = vram;
-       nvdev->base.gart_size = gart;
-       nvdev->base.vram_limit =
-               (nvdev->base.vram_size * nvdev->vram_limit_percent) / 100;
+
        nvdev->base.gart_limit =
                (nvdev->base.gart_size * nvdev->gart_limit_percent) / 100;
 
-       *pdev = &nvdev->base;
+       ret = pthread_mutex_init(&nvdev->lock, NULL);
+       DRMINITLISTHEAD(&nvdev->bo_list);
+done:
+       if (ret)
+               nouveau_device_del(pdev);
+       return ret;
+}
+
+int
+nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev)
+{
+       struct nouveau_drm *drm;
+       struct nouveau_device_priv *nvdev;
+       int ret;
+
+       ret = nouveau_drm_new(fd, &drm);
+       if (ret)
+               return ret;
+       drm->nvif = false;
+
+       ret = nouveau_device_new(&drm->client, NV_DEVICE,
+                                &(struct nv_device_v0) {
+                                       .device = ~0ULL,
+                                }, sizeof(struct nv_device_v0), pdev);
+       if (ret) {
+               nouveau_drm_del(&drm);
+               return ret;
+       }
+
+       nvdev = nouveau_device(*pdev);
+       nvdev->base.fd = drm->fd;
+       nvdev->base.drm_version = drm->drm_version;
+       nvdev->base.lib_version = drm->lib_version;
+       nvdev->close = close;
        return 0;
 }
 
@@ -320,12 +356,15 @@ nouveau_device_del(struct nouveau_device **pdev)
 {
        struct nouveau_device_priv *nvdev = nouveau_device(*pdev);
        if (nvdev) {
-               struct nouveau_drm *drm = nouveau_drm(&nvdev->base.object);
                free(nvdev->client);
-               nouveau_drm_del(&drm);
                pthread_mutex_destroy(&nvdev->lock);
-               if (nvdev->close)
-                       drmClose(nvdev->base.fd);
+               if (nvdev->base.fd >= 0) {
+                       struct nouveau_drm *drm =
+                               nouveau_drm(&nvdev->base.object);
+                       nouveau_drm_del(&drm);
+                       if (nvdev->close)
+                               drmClose(nvdev->base.fd);
+               }
                free(nvdev);
                *pdev = NULL;
        }
diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
index a693acf..f3cf8f5 100644
--- a/nouveau/nouveau.h

Reply via email to