libdrm: Changes to 'upstream-unstable'
.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 <michal.winiarski@intel.com>
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 <michal.winiarski@intel.com>
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 <michal.winiarski@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
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 <bskeggs@redhat.com>
Date: Tue Nov 24 11:57:39 2015 +1000
Bump version for release
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Tested-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
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 <bskeggs@redhat.com>
Date: Thu Nov 26 08:24:55 2015 +1000
nouveau: clean up nouveau.h, noting deprecated members/functions
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Tested-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
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 <bskeggs@redhat.com>
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 <bskeggs@redhat.com>
Tested-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
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 <bskeggs@redhat.com>
Date: Tue Nov 24 11:21:05 2015 +1000
nouveau: add new interface to create a nouveau_device
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Tested-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
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 to: