libdrm: Changes to 'debian-unstable'
debian/changelog | 16
debian/control | 26
debian/libdrm-nouveau1.install | 1
debian/libdrm-nouveau1.symbols | 59 +
debian/patches/03_revert_abi_change.diff | 1224 +++++++++++++++++++++++++++++++
debian/patches/series | 1
debian/rules | 10
7 files changed, 1337 insertions(+)
New commits:
commit eebc0b4f31062ef36d918f8762c5b85da78fc027
Author: Cyril Brulebois <kibi@debian.org>
Date: Wed Apr 14 13:03:08 2010 +0200
Upload to unstable.
diff --git a/debian/changelog b/debian/changelog
index 79153c3..bc62c1d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+libdrm (2.4.18-5) unstable; urgency=low
+
+ * Upload to unstable.
+
+ -- Cyril Brulebois <kibi@debian.org> Wed, 14 Apr 2010 13:02:34 +0200
+
libdrm (2.4.18-4) experimental; urgency=low
* Steal 03_revert_abi_change.diff from Ubuntu to revert the nouveau ABI
commit 197bdde16f9c405936f7a6cdce30322770022562
Author: Brice Goglin <bgoglin@debian.org>
Date: Wed Mar 24 22:19:10 2010 +0100
Prepare changelog for upload
diff --git a/debian/changelog b/debian/changelog
index c1d3dda..79153c3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-libdrm (2.4.18-4) UNRELEASED; urgency=low
+libdrm (2.4.18-4) experimental; urgency=low
* Steal 03_revert_abi_change.diff from Ubuntu to revert the nouveau ABI
change. Current Debian kernels support only the old ABI.
@@ -6,7 +6,7 @@ libdrm (2.4.18-4) UNRELEASED; urgency=low
* Build a libdrm-nouveau1 package on Linux architectures (Closes: #568162).
Patch adapted from the Ubuntu package. Thanks Sven Joachim!
- -- Brice Goglin <bgoglin@debian.org> Wed, 24 Mar 2010 22:12:36 +0100
+ -- Brice Goglin <bgoglin@debian.org> Wed, 24 Mar 2010 22:27:00 +0100
libdrm (2.4.18-3) unstable; urgency=low
commit 9f62499e2dd1df046001d174d9a6518b3db929e4
Author: Brice Goglin <bgoglin@debian.org>
Date: Wed Mar 24 22:18:36 2010 +0100
Build a libdrm-nouveau1 package on Linux architectures (Closes: #568162).
diff --git a/debian/changelog b/debian/changelog
index fe4f1f0..c1d3dda 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,6 +3,8 @@ libdrm (2.4.18-4) UNRELEASED; urgency=low
* Steal 03_revert_abi_change.diff from Ubuntu to revert the nouveau ABI
change. Current Debian kernels support only the old ABI.
Thanks Sven Joachim!
+ * Build a libdrm-nouveau1 package on Linux architectures (Closes: #568162).
+ Patch adapted from the Ubuntu package. Thanks Sven Joachim!
-- Brice Goglin <bgoglin@debian.org> Wed, 24 Mar 2010 22:12:36 +0100
diff --git a/debian/control b/debian/control
index 65f013a..cf271d8 100644
--- a/debian/control
+++ b/debian/control
@@ -23,6 +23,7 @@ Depends:
libdrm2 (= ${binary:Version}),
libdrm-intel1 (= ${binary:Version}) [amd64 i386 kfreebsd-amd64 kfreebsd-i386],
libdrm-radeon1 (= ${binary:Version}) [linux-any],
+ libdrm-nouveau1 (= ${binary:Version}) [linux-any],
${misc:Depends},
Replaces:
linux-libc-dev (<< 2.6.32-10)
@@ -93,6 +94,31 @@ Description: Userspace interface to intel-specific kernel DRM services -- debugg
.
This package provides the debugging symbols for the libdrm-intel1 package.
+Package: libdrm-nouveau1
+Section: libs
+Architecture: linux-any
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+Description: Userspace interface to nouveau-specific kernel DRM services -- runtime
+ This library implements the userspace interface to the nouveau-specific kernel
+ DRM services. DRM stands for "Direct Rendering Manager", which is the
+ kernelspace portion of the "Direct Rendering Infrastructure" (DRI). The DRI is
+ currently used on Linux to provide hardware-accelerated OpenGL drivers.
+
+Package: libdrm-nouveau1-dbg
+Section: debug
+Priority: extra
+Architecture: linux-any
+Depends: libdrm-nouveau1 (= ${binary:Version}),
+ ${misc:Depends},
+Description: Userspace interface to nouveau-specific kernel DRM -- debugging symbols
+ This library implements the userspace interface to the kernel DRM services.
+ DRM stands for "Direct Rendering Manager", which is the kernelspace portion
+ of the "Direct Rendering Infrastructure" (DRI). The DRI is currently used on
+ Linux to provide hardware-accelerated OpenGL drivers.
+ .
+ This package provides the debugging symbols for the libdrm-nouveau1 package.
+
Package: libdrm-radeon1
Section: libs
Architecture: linux-any
diff --git a/debian/libdrm-nouveau1.install b/debian/libdrm-nouveau1.install
new file mode 100644
index 0000000..7650858
--- /dev/null
+++ b/debian/libdrm-nouveau1.install
@@ -0,0 +1 @@
+usr/lib/libdrm_nouveau.so.*
diff --git a/debian/libdrm-nouveau1.symbols b/debian/libdrm-nouveau1.symbols
new file mode 100644
index 0000000..48ce118
--- /dev/null
+++ b/debian/libdrm-nouveau1.symbols
@@ -0,0 +1,59 @@
+libdrm_nouveau.so.1 libdrm-nouveau1 #MINVER#
+#MISSING: 2.4.12+git20090729.5a73f066# dma@Base 2.4.4
+ nouveau_bo_busy@Base 2.4.4
+ nouveau_bo_emit_buffer@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_bo_fake@Base 2.4.4
+ nouveau_bo_handle_get@Base 2.4.4
+ nouveau_bo_handle_ref@Base 2.4.4
+ nouveau_bo_init@Base 2.4.4
+ nouveau_bo_map@Base 2.4.4
+ nouveau_bo_map_flush@Base 2.4.11-1ubuntu1~
+ nouveau_bo_map_range@Base 2.4.11-1ubuntu1~
+ nouveau_bo_new@Base 2.4.4
+ nouveau_bo_new_tile@Base 2.4.11-1ubuntu1~
+ nouveau_bo_pending@Base 2.4.16
+ nouveau_bo_pin@Base 2.4.4
+ nouveau_bo_ref@Base 2.4.4
+ nouveau_bo_takedown@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_bo_tile@Base 2.4.4
+ nouveau_bo_unmap@Base 2.4.4
+ nouveau_bo_unpin@Base 2.4.4
+ nouveau_bo_user@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_bo_validate_nomm@Base 2.4.4
+ nouveau_bo_wrap@Base 2.4.11-1ubuntu1~
+ nouveau_channel_alloc@Base 2.4.4
+ nouveau_channel_free@Base 2.4.4
+ nouveau_device_close@Base 2.4.4
+ nouveau_device_get_param@Base 2.4.4
+ nouveau_device_open@Base 2.4.4
+ nouveau_device_open_existing@Base 2.4.4
+ nouveau_device_set_param@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_dma_channel_init@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_dma_kickoff@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_dma_wait@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_emit@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_flush@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_new@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_ref@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_signal_cb@Base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_wait@Base 2.4.4
+ nouveau_grobj_alloc@Base 2.4.4
+ nouveau_grobj_autobind@Base 2.4.4
+ nouveau_grobj_free@Base 2.4.4
+ nouveau_grobj_ref@Base 2.4.4
+ nouveau_notifier_alloc@Base 2.4.4
+ nouveau_notifier_free@Base 2.4.4
+ nouveau_notifier_reset@Base 2.4.4
+ nouveau_notifier_return_val@Base 2.4.4
+ nouveau_notifier_status@Base 2.4.4
+ nouveau_notifier_wait_status@Base 2.4.4
+ nouveau_pushbuf_emit_reloc@Base 2.4.4
+ nouveau_pushbuf_fini@Base 2.4.17-1ubuntu1~
+ nouveau_pushbuf_flush@Base 2.4.4
+ nouveau_pushbuf_init@Base 2.4.4
+ nouveau_pushbuf_marker_emit@Base 2.4.16
+ nouveau_pushbuf_marker_undo@Base 2.4.16
+ nouveau_resource_alloc@Base 2.4.4
+ nouveau_resource_destroy@Base 2.4.18
+ nouveau_resource_free@Base 2.4.4
+ nouveau_resource_init@Base 2.4.4
diff --git a/debian/rules b/debian/rules
index dede329..471ea74 100755
--- a/debian/rules
+++ b/debian/rules
@@ -24,10 +24,14 @@ else
endif
ifeq (linux, $(DEB_HOST_ARCH_OS))
confflags += --enable-udev
+ confflags += --enable-nouveau-experimental-api
+ NOUVEAU = yes
confflags += --enable-radeon
RADEON = yes
else
confflags += --disable-udev
+ confflags += --disable-nouveau-experimental-api
+ NOUVEAU = no
confflags += --disable-radeon
RADEON = no
endif
@@ -121,6 +125,9 @@ binary-arch: build install
ifeq ($(INTEL), yes)
dh_strip -plibdrm-intel1 --dbg-package=libdrm-intel1-dbg
endif
+ifeq ($(NOUVEAU), yes)
+ dh_strip -plibdrm-nouveau1 --dbg-package=libdrm-nouveau1-dbg
+endif
ifeq ($(RADEON), yes)
dh_strip -plibdrm-radeon1 --dbg-package=libdrm-radeon1-dbg
endif
@@ -131,6 +138,9 @@ endif
ifeq ($(INTEL), yes)
dh_makeshlibs -plibdrm-intel1 -V'libdrm-intel1 (>= 2.4.16)' -- -c4
endif
+ifeq ($(NOUVEAU), yes)
+ dh_makeshlibs -plibdrm-nouveau1 -V'libdrm-nouveau1 (>= 2.4.16)' -- -c4
+endif
ifeq ($(RADEON), yes)
dh_makeshlibs -plibdrm-radeon1 -V'libdrm-radeon1 (>= 2.4.17)' -- -c4
endif
commit 3279d82034f7c5d0e968fff8bbdab212f39f7fba
Author: Brice Goglin <bgoglin@debian.org>
Date: Wed Mar 24 22:12:17 2010 +0100
Steal 03_revert_abi_change.diff from Ubuntu to revert the nouveau ABI change
diff --git a/debian/changelog b/debian/changelog
index ed279c5..fe4f1f0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+libdrm (2.4.18-4) UNRELEASED; urgency=low
+
+ * Steal 03_revert_abi_change.diff from Ubuntu to revert the nouveau ABI
+ change. Current Debian kernels support only the old ABI.
+ Thanks Sven Joachim!
+
+ -- Brice Goglin <bgoglin@debian.org> Wed, 24 Mar 2010 22:12:36 +0100
+
libdrm (2.4.18-3) unstable; urgency=low
* Include full SONAME in libdrm*.install to prevent accidental breakage.
diff --git a/debian/patches/03_revert_abi_change.diff b/debian/patches/03_revert_abi_change.diff
new file mode 100644
index 0000000..12dd8f6
--- /dev/null
+++ b/debian/patches/03_revert_abi_change.diff
@@ -0,0 +1,1224 @@
+Revert nouveau ABI change to match what is in 2.6.33.
+
+This reverts commits after b496c63143e9a4ca02011582329bce2df99d9b7c
+
+diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
+index a6a9f4a..f745948 100644
+--- a/include/drm/nouveau_drm.h
++++ b/include/drm/nouveau_drm.h
+@@ -25,14 +25,13 @@
+ #ifndef __NOUVEAU_DRM_H__
+ #define __NOUVEAU_DRM_H__
+
+-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16
++#define NOUVEAU_DRM_HEADER_PATCHLEVEL 15
+
+ struct drm_nouveau_channel_alloc {
+ uint32_t fb_ctxdma_handle;
+ uint32_t tt_ctxdma_handle;
+
+ int channel;
+- uint32_t pushbuf_domains;
+
+ /* Notifier memory */
+ uint32_t notifier_handle;
+@@ -110,58 +109,68 @@ struct drm_nouveau_gem_new {
+ uint32_t align;
+ };
+
+-#define NOUVEAU_GEM_MAX_BUFFERS 1024
+-struct drm_nouveau_gem_pushbuf_bo_presumed {
+- uint32_t valid;
+- uint32_t domain;
+- uint64_t 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;
+- struct drm_nouveau_gem_pushbuf_bo_presumed presumed;
++ uint32_t presumed_ok;
++ uint32_t presumed_domain;
++ uint64_t presumed_offset;
+ };
+
+ #define NOUVEAU_GEM_RELOC_LOW (1 << 0)
+ #define NOUVEAU_GEM_RELOC_HIGH (1 << 1)
+ #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 reloc_index;
+ uint32_t flags;
+ uint32_t data;
+ uint32_t vor;
+ uint32_t 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;
+-};
++#define NOUVEAU_GEM_MAX_BUFFERS 1024
++#define NOUVEAU_GEM_MAX_RELOCS 1024
+
+ struct drm_nouveau_gem_pushbuf {
+ uint32_t channel;
++ uint32_t nr_dwords;
+ uint32_t nr_buffers;
++ uint32_t nr_relocs;
++ uint64_t dwords;
+ uint64_t buffers;
++ uint64_t relocs;
++};
++
++struct drm_nouveau_gem_pushbuf_call {
++ uint32_t channel;
++ uint32_t handle;
++ uint32_t offset;
++ uint32_t nr_buffers;
+ uint32_t nr_relocs;
+- uint32_t nr_push;
++ uint32_t nr_dwords;
++ uint64_t buffers;
+ uint64_t relocs;
+- uint64_t push;
+ uint32_t suffix0;
+ uint32_t suffix1;
++ /* below only accessed for CALL2 */
+ uint64_t vram_available;
+ uint64_t gart_available;
+ };
+
++struct drm_nouveau_gem_pin {
++ uint32_t handle;
++ uint32_t domain;
++ uint64_t offset;
++};
++
++struct drm_nouveau_gem_unpin {
++ uint32_t handle;
++};
++
+ #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001
+ #define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002
+ #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004
+@@ -174,6 +183,14 @@ struct drm_nouveau_gem_cpu_fini {
+ uint32_t handle;
+ };
+
++struct drm_nouveau_gem_tile {
++ uint32_t handle;
++ uint32_t offset;
++ uint32_t size;
++ uint32_t tile_mode;
++ uint32_t tile_flags;
++};
++
+ enum nouveau_bus_type {
+ NV_AGP = 0,
+ NV_PCI = 1,
+@@ -183,17 +200,22 @@ enum nouveau_bus_type {
+ struct drm_nouveau_sarea {
+ };
+
+-#define DRM_NOUVEAU_GETPARAM 0x00
+-#define DRM_NOUVEAU_SETPARAM 0x01
+-#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02
+-#define DRM_NOUVEAU_CHANNEL_FREE 0x03
+-#define DRM_NOUVEAU_GROBJ_ALLOC 0x04
+-#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05
+-#define DRM_NOUVEAU_GPUOBJ_FREE 0x06
++#define DRM_NOUVEAU_CARD_INIT 0x00
++#define DRM_NOUVEAU_GETPARAM 0x01
++#define DRM_NOUVEAU_SETPARAM 0x02
++#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03
++#define DRM_NOUVEAU_CHANNEL_FREE 0x04
++#define DRM_NOUVEAU_GROBJ_ALLOC 0x05
++#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06
++#define DRM_NOUVEAU_GPUOBJ_FREE 0x07
+ #define DRM_NOUVEAU_GEM_NEW 0x40
+ #define DRM_NOUVEAU_GEM_PUSHBUF 0x41
+-#define DRM_NOUVEAU_GEM_CPU_PREP 0x42
+-#define DRM_NOUVEAU_GEM_CPU_FINI 0x43
+-#define DRM_NOUVEAU_GEM_INFO 0x44
++#define DRM_NOUVEAU_GEM_PUSHBUF_CALL 0x42
++#define DRM_NOUVEAU_GEM_PIN 0x43 /* !KMS only */
++#define DRM_NOUVEAU_GEM_UNPIN 0x44 /* !KMS only */
++#define DRM_NOUVEAU_GEM_CPU_PREP 0x45
++#define DRM_NOUVEAU_GEM_CPU_FINI 0x46
++#define DRM_NOUVEAU_GEM_INFO 0x47
++#define DRM_NOUVEAU_GEM_PUSHBUF_CALL2 0x48
+
+ #endif /* __NOUVEAU_DRM_H__ */
+diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am
+index 5d759c5..70bbbb2 100644
+--- a/nouveau/Makefile.am
++++ b/nouveau/Makefile.am
+@@ -18,8 +18,7 @@ libdrm_nouveau_la_SOURCES = \
+ nouveau_notifier.c \
+ nouveau_bo.c \
+ nouveau_resource.c \
+- nouveau_private.h \
+- nouveau_reloc.c
++ nouveau_private.h
+
+ libdrm_nouveaucommonincludedir = ${includedir}/nouveau
+ libdrm_nouveaucommoninclude_HEADERS = \
+@@ -30,8 +29,7 @@ libdrm_nouveaucommoninclude_HEADERS = \
+ nouveau_pushbuf.h \
+ nouveau_bo.h \
+ nouveau_resource.h \
+- nouveau_class.h \
+- nouveau_reloc.h
++ nouveau_class.h
+
+
+ libdrm_nouveauincludedir = ${includedir}/drm
+diff --git a/nouveau/nouveau_bo.c b/nouveau/nouveau_bo.c
+index 4973636..10cc8a6 100644
+--- a/nouveau/nouveau_bo.c
++++ b/nouveau/nouveau_bo.c
+@@ -201,6 +201,14 @@ nouveau_bo_new_tile(struct nouveau_device *dev, uint32_t flags, int align,
+ nouveau_bo_ref(NULL, (void *)nvbo);
+ return ret;
+ }
++
++ if (flags & NOUVEAU_BO_PIN) {
++ ret = nouveau_bo_pin((void *)nvbo, nvbo->flags);
++ if (ret) {
++ nouveau_bo_ref(NULL, (void *)nvbo);
++ return ret;
++ }
++ }
+ }
+
+ *bo = &nvbo->base;
+@@ -211,7 +219,16 @@ int
+ nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
+ int size, struct nouveau_bo **bo)
+ {
+- return nouveau_bo_new_tile(dev, flags, align, size, 0, 0, bo);
++ uint32_t tile_flags = 0;
++
++ if (flags & NOUVEAU_BO_TILED) {
++ if (flags & NOUVEAU_BO_ZTILE)
++ tile_flags = 0x2800;
++ else
++ tile_flags = 0x7000;
++ }
++
++ return nouveau_bo_new_tile(dev, flags, align, size, 0, tile_flags, bo);
+ }
+
+ int
+@@ -466,6 +483,62 @@ nouveau_bo_unmap(struct nouveau_bo *bo)
+ }
+
+ int
++nouveau_bo_pin(struct nouveau_bo *bo, uint32_t flags)
++{
++ struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
++ struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++ struct drm_nouveau_gem_pin req;
++ int ret;
++
++ if (nvbo->pinned)
++ return 0;
++
++ if (!nvbo->handle)
++ return -EINVAL;
++
++ /* Now force it to stay put :) */
++ req.handle = nvbo->handle;
++ req.domain = 0;
++ if (flags & NOUVEAU_BO_VRAM)
++ req.domain |= NOUVEAU_GEM_DOMAIN_VRAM;
++ if (flags & NOUVEAU_BO_GART)
++ req.domain |= NOUVEAU_GEM_DOMAIN_GART;
++
++ ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PIN, &req,
++ sizeof(struct drm_nouveau_gem_pin));
++ if (ret)
++ return ret;
++ nvbo->offset = req.offset;
++ nvbo->domain = req.domain;
++ nvbo->pinned = 1;
++
++ /* Fill in public nouveau_bo members */
++ if (nvbo->domain & NOUVEAU_GEM_DOMAIN_VRAM)
++ bo->flags = NOUVEAU_BO_VRAM;
++ if (nvbo->domain & NOUVEAU_GEM_DOMAIN_GART)
++ bo->flags = NOUVEAU_BO_GART;
++ bo->offset = nvbo->offset;
++
++ return 0;
++}
++
++void
++nouveau_bo_unpin(struct nouveau_bo *bo)
++{
++ struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
++ struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++ struct drm_nouveau_gem_unpin req;
++
++ if (!nvbo->pinned)
++ return;
++
++ req.handle = nvbo->handle;
++ drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_UNPIN, &req, sizeof(req));
++
++ nvbo->pinned = bo->offset = bo->flags = 0;
++}
++
++int
+ nouveau_bo_busy(struct nouveau_bo *bo, uint32_t access)
+ {
+ return nouveau_bo_wait(bo, (access & NOUVEAU_BO_WR), 1, 1);
+@@ -492,7 +565,7 @@ nouveau_bo_pending(struct nouveau_bo *bo)
+ struct drm_nouveau_gem_pushbuf_bo *
+ nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
+ {
+- struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
++ struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+ struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+ struct drm_nouveau_gem_pushbuf_bo *pbbo;
+ struct nouveau_bo *ref = NULL;
+@@ -534,8 +607,8 @@ nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
+ pbbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART;
+ pbbo->read_domains = 0;
+ pbbo->write_domains = 0;
+- pbbo->presumed.domain = nvbo->domain;
+- pbbo->presumed.offset = nvbo->offset;
+- pbbo->presumed.valid = 1;
++ pbbo->presumed_domain = nvbo->domain;
++ pbbo->presumed_offset = nvbo->offset;
++ pbbo->presumed_ok = 1;
+ return pbbo;
+ }
+diff --git a/nouveau/nouveau_bo.h b/nouveau/nouveau_bo.h
+index 1e77ab0..fdad63e 100644
+--- a/nouveau/nouveau_bo.h
++++ b/nouveau/nouveau_bo.h
+@@ -30,9 +30,13 @@
+ #define NOUVEAU_BO_WR (1 << 3)
+ #define NOUVEAU_BO_RDWR (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
+ #define NOUVEAU_BO_MAP (1 << 4)
++#define NOUVEAU_BO_PIN (1 << 5)
+ #define NOUVEAU_BO_LOW (1 << 6)
+ #define NOUVEAU_BO_HIGH (1 << 7)
+ #define NOUVEAU_BO_OR (1 << 8)
++#define NOUVEAU_BO_LOCAL (1 << 9)
++#define NOUVEAU_BO_TILED (1 << 10)
++#define NOUVEAU_BO_ZTILE (1 << 11)
+ #define NOUVEAU_BO_INVAL (1 << 12)
+ #define NOUVEAU_BO_NOSYNC (1 << 13)
+ #define NOUVEAU_BO_NOWAIT (1 << 14)
+@@ -48,6 +52,10 @@ struct nouveau_bo {
+
+ uint32_t tile_mode;
+ uint32_t tile_flags;
++
++ /* Available when buffer is pinned *only* */
++ uint32_t flags;
++ uint64_t offset;
+ };
+
+ int
+@@ -90,6 +98,12 @@ void
+ nouveau_bo_unmap(struct nouveau_bo *);
+
+ int
++nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
++
++void
++nouveau_bo_unpin(struct nouveau_bo *);
++
++int
+ nouveau_bo_busy(struct nouveau_bo *, uint32_t access);
+
+ uint32_t
+diff --git a/nouveau/nouveau_channel.h b/nouveau/nouveau_channel.h
+index ddcf8e4..294f749 100644
+--- a/nouveau/nouveau_channel.h
++++ b/nouveau/nouveau_channel.h
+@@ -29,12 +29,11 @@ struct nouveau_subchannel {
+ };
+
+ struct nouveau_channel {
+- uint32_t *cur;
+- uint32_t *end;
+-
+ struct nouveau_device *device;
+ int id;
+
++ struct nouveau_pushbuf *pushbuf;
++
+ struct nouveau_grobj *nullobj;
+ struct nouveau_grobj *vram;
+ struct nouveau_grobj *gart;
+diff --git a/nouveau/nouveau_device.c b/nouveau/nouveau_device.c
+index c525391..0982d3b 100644
+--- a/nouveau/nouveau_device.c
++++ b/nouveau/nouveau_device.c
+@@ -26,7 +26,7 @@
+
+ #include "nouveau_private.h"
+
+-#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 16
++#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 15
+ #error nouveau_drm.h does not match expected patchlevel, update libdrm.
+ #endif
+
+@@ -54,6 +54,12 @@ nouveau_device_open_existing(struct nouveau_device **dev, int close,
+ nvdev->ctx = ctx;
+ nvdev->needs_close = close;
+
++ ret = drmCommandNone(nvdev->fd, DRM_NOUVEAU_CARD_INIT);
++ if (ret) {
++ nouveau_device_close((void *)&nvdev);
++ return ret;
++ }
++
+ ret = nouveau_device_get_param(&nvdev->base,
+ NOUVEAU_GETPARAM_VM_VRAM_BASE, &value);
+ if (ret) {
+diff --git a/nouveau/nouveau_private.h b/nouveau/nouveau_private.h
+index c08fa38..39758d1 100644
+--- a/nouveau/nouveau_private.h
++++ b/nouveau/nouveau_private.h
+@@ -35,11 +35,14 @@
+ #include "nouveau_bo.h"
+ #include "nouveau_resource.h"
+ #include "nouveau_pushbuf.h"
+-#include "nouveau_reloc.h"
+
+ #define CALPB_BUFFERS 4
+ #define CALPB_BUFSZ 16384
+ struct nouveau_pushbuf_priv {
++ struct nouveau_pushbuf base;
++
++ int no_aper_update;
++ int use_cal;
+ uint32_t cal_suffix0;
+ uint32_t cal_suffix1;
+ struct nouveau_bo *buffer[CALPB_BUFFERS];
+@@ -47,19 +50,15 @@ struct nouveau_pushbuf_priv {
+ int current_offset;
+
+ unsigned *pushbuf;
+- unsigned size;
++ unsigned size;
+
+- uint32_t *marker;
+- unsigned marker_offset;
++ unsigned marker;
+ unsigned marker_relocs;
+- unsigned marker_push;
+
+ struct drm_nouveau_gem_pushbuf_bo *buffers;
+ unsigned nr_buffers;
+ struct drm_nouveau_gem_pushbuf_reloc *relocs;
+ unsigned nr_relocs;
+- struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
+- unsigned nr_push;
+ };
+ #define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
+
+diff --git a/nouveau/nouveau_pushbuf.c b/nouveau/nouveau_pushbuf.c
+index 28b8018..7da3a47 100644
+--- a/nouveau/nouveau_pushbuf.c
++++ b/nouveau/nouveau_pushbuf.c
+@@ -31,7 +31,7 @@
+ #define PB_MIN_USER_DWORDS 2048
+
+ static int
+-nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
++nouveau_pushbuf_space_call(struct nouveau_channel *chan, unsigned min)
+ {
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+ struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+@@ -41,8 +41,8 @@ nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
+ if (min < PB_MIN_USER_DWORDS)
+ min = PB_MIN_USER_DWORDS;
+
+- nvpb->current_offset = chan->cur - nvpb->pushbuf;
+- if (chan->cur + min + 2 <= chan->end)
++ nvpb->current_offset = nvpb->base.cur - nvpb->pushbuf;
++ if (nvpb->current_offset + min + 2 <= nvpb->size)
+ return 0;
+
+ nvpb->current++;
+@@ -58,13 +58,38 @@ nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
+ nvpb->pushbuf = bo->map;
+ nvpb->current_offset = 0;
+
+- chan->cur = nvpb->pushbuf;
+- chan->end = nvpb->pushbuf + nvpb->size;
++ nvpb->base.channel = chan;
++ nvpb->base.remaining = nvpb->size;
++ nvpb->base.cur = nvpb->pushbuf;
+
+ nouveau_bo_unmap(bo);
+ return 0;
+ }
+
++static int
++nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
++{
++ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
++ struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
++
++ if (nvpb->use_cal)
++ return nouveau_pushbuf_space_call(chan, min);
++
++ if (nvpb->pushbuf) {
++ free(nvpb->pushbuf);
++ nvpb->pushbuf = NULL;
++ }
++
++ nvpb->size = min < PB_MIN_USER_DWORDS ? PB_MIN_USER_DWORDS : min;
++ nvpb->pushbuf = malloc(sizeof(uint32_t) * nvpb->size);
++
++ nvpb->base.channel = chan;
++ nvpb->base.remaining = nvpb->size;
++ nvpb->base.cur = nvpb->pushbuf;
++
++ return 0;
++}
++
+ static void
+ nouveau_pushbuf_fini_call(struct nouveau_channel *chan)
+ {
+@@ -74,43 +99,46 @@ nouveau_pushbuf_fini_call(struct nouveau_channel *chan)
+
+ for (i = 0; i < CALPB_BUFFERS; i++)
+ nouveau_bo_ref(NULL, &nvpb->buffer[i]);
++ nvpb->use_cal = 0;
+ nvpb->pushbuf = NULL;
+ }
+
+-static int
++static void
+ nouveau_pushbuf_init_call(struct nouveau_channel *chan)
+ {
+- struct drm_nouveau_gem_pushbuf req;
++ struct drm_nouveau_gem_pushbuf_call req;
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+ struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+ struct nouveau_device *dev = chan->device;
+- uint32_t flags = 0;
+ int i, ret;
+
+- if (nvchan->drm.pushbuf_domains & NOUVEAU_GEM_DOMAIN_GART)
+- flags |= NOUVEAU_BO_GART;
+- else
+- flags |= NOUVEAU_BO_VRAM;
+-
+ req.channel = chan->id;
+- req.nr_push = 0;
++ req.handle = 0;
+ ret = drmCommandWriteRead(nouveau_device(dev)->fd,
+- DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req));
+- if (ret)
+- return ret;
++ DRM_NOUVEAU_GEM_PUSHBUF_CALL2,
++ &req, sizeof(req));
++ if (ret) {
++ ret = drmCommandWriteRead(nouveau_device(dev)->fd,
++ DRM_NOUVEAU_GEM_PUSHBUF_CALL2,
++ &req, sizeof(req));
++ if (ret)
++ return;
++
++ nvpb->no_aper_update = 1;
++ }
+
+ for (i = 0; i < CALPB_BUFFERS; i++) {
+- ret = nouveau_bo_new(dev, flags | NOUVEAU_BO_MAP,
++ ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 0, CALPB_BUFSZ, &nvpb->buffer[i]);
+ if (ret) {
+ nouveau_pushbuf_fini_call(chan);
+- return ret;
++ return;
+ }
+ }
+
++ nvpb->use_cal = 1;
+ nvpb->cal_suffix0 = req.suffix0;
+ nvpb->cal_suffix1 = req.suffix1;
+- return 0;
+ }
+
+ int
+@@ -120,18 +148,25 @@ nouveau_pushbuf_init(struct nouveau_channel *chan)
+ struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+ int ret;
+
+- ret = nouveau_pushbuf_init_call(chan);
+- if (ret)
+- return ret;
++ nouveau_pushbuf_init_call(chan);
+
+ ret = nouveau_pushbuf_space(chan, 0);
+- if (ret)
+- return ret;
++ if (ret) {
++ if (nvpb->use_cal) {
++ nouveau_pushbuf_fini_call(chan);
++ ret = nouveau_pushbuf_space(chan, 0);
++ }
++
++ if (ret)
++ return ret;
++ }
+
+ nvpb->buffers = calloc(NOUVEAU_GEM_MAX_BUFFERS,
+ sizeof(struct drm_nouveau_gem_pushbuf_bo));
+ nvpb->relocs = calloc(NOUVEAU_GEM_MAX_RELOCS,
+ sizeof(struct drm_nouveau_gem_pushbuf_reloc));
++
++ chan->pushbuf = &nvpb->base;
+ return 0;
+ }
+
+@@ -145,129 +180,92 @@ nouveau_pushbuf_fini(struct nouveau_channel *chan)
+ free(nvpb->relocs);
+ }
+
+-static int
+-nouveau_pushbuf_bo_add(struct nouveau_channel *chan, struct nouveau_bo *bo,
+- unsigned offset, unsigned length)
+-{
+- struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+- struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+- struct drm_nouveau_gem_pushbuf_push *p = &nvpb->push[nvpb->nr_push++];
+- struct drm_nouveau_gem_pushbuf_bo *pbbo;
+- struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+-
+- pbbo = nouveau_bo_emit_buffer(chan, bo);
+- if (!pbbo)
+- return -ENOMEM;
+- pbbo->valid_domains &= nvchan->drm.pushbuf_domains;
+- pbbo->read_domains |= nvchan->drm.pushbuf_domains;
+- nvbo->pending_refcnt++;
+-
+- p->bo_index = pbbo - nvpb->buffers;
+- p->offset = offset;
+- p->length = length;
+- return 0;
+-}
+-
+-int
+-nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
+- unsigned offset, unsigned length)
+-{
+- struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
+- int ret, len;
+-
+- if ((AVAIL_RING(chan) + nvpb->current_offset) != nvpb->size) {
+- if (nvpb->cal_suffix0 || nvpb->cal_suffix1) {
+- *(chan->cur++) = nvpb->cal_suffix0;
+- *(chan->cur++) = nvpb->cal_suffix1;
+- }
+-
+- len = (chan->cur - nvpb->pushbuf) - nvpb->current_offset;
+-
+- ret = nouveau_pushbuf_bo_add(chan, nvpb->buffer[nvpb->current],
+- nvpb->current_offset * 4, len * 4);
+- if (ret)
+- return ret;
+-
+- nvpb->current_offset += len;
+- }
+-
+- return bo ? nouveau_pushbuf_bo_add(chan, bo, offset, length) : 0;
+-}
+-
+-static void
+-nouveau_pushbuf_bo_unref(struct nouveau_pushbuf_priv *nvpb, int index)
+-{
+- struct drm_nouveau_gem_pushbuf_bo *pbbo = &nvpb->buffers[index];
+- struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
+- struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+-
+- if (--nvbo->pending_refcnt)
+- return;
+-
+- if (pbbo->presumed.valid == 0) {
+- nvbo->domain = pbbo->presumed.domain;
+- nvbo->offset = pbbo->presumed.offset;
+- }
+-
+- nvbo->pending = NULL;
+- nouveau_bo_ref(NULL, &bo);
+-
+- /* we only ever remove from the tail of the pending lists,
+- * so this is safe.
+- */
+- nvpb->nr_buffers--;
+-}
+-
+ int
+ nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
+ {
+ struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+ struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+- struct drm_nouveau_gem_pushbuf req;
+ unsigned i;
+ int ret;
+
+- ret = nouveau_pushbuf_submit(chan, NULL, 0, 0);
+- if (ret)
+- return ret;
+-
+- if (!nvpb->nr_push)
++ if (nvpb->base.remaining == nvpb->size)
+ return 0;
+
+- req.channel = chan->id;
+- req.nr_push = nvpb->nr_push;
+- req.push = (uint64_t)(unsigned long)nvpb->push;
+- req.nr_buffers = nvpb->nr_buffers;
+- req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
+- req.nr_relocs = nvpb->nr_relocs;
+- req.relocs = (uint64_t)(unsigned long)nvpb->relocs;
+- req.suffix0 = nvpb->cal_suffix0;
+- req.suffix1 = nvpb->cal_suffix1;
+-
+- do {
+- ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
++ if (nvpb->use_cal) {
++ struct drm_nouveau_gem_pushbuf_call req;
++
++ *(nvpb->base.cur++) = nvpb->cal_suffix0;
++ *(nvpb->base.cur++) = nvpb->cal_suffix1;
++ if (nvpb->base.remaining > 2) /* space() will fixup if not */
++ nvpb->base.remaining -= 2;
++
++restart_cal:
++ req.channel = chan->id;
++ req.handle = nvpb->buffer[nvpb->current]->handle;
++ req.offset = nvpb->current_offset * 4;
++ req.nr_buffers = nvpb->nr_buffers;
++ req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
++ req.nr_relocs = nvpb->nr_relocs;
++ req.relocs = (uint64_t)(unsigned long)nvpb->relocs;
++ req.nr_dwords = (nvpb->base.cur - nvpb->pushbuf) -
++ nvpb->current_offset;
++ req.suffix0 = nvpb->cal_suffix0;
++ req.suffix1 = nvpb->cal_suffix1;
++ ret = drmCommandWriteRead(nvdev->fd, nvpb->no_aper_update ?
++ DRM_NOUVEAU_GEM_PUSHBUF_CALL :
++ DRM_NOUVEAU_GEM_PUSHBUF_CALL2,
+ &req, sizeof(req));
+- } while (ret == -EAGAIN);
+- nvpb->cal_suffix0 = req.suffix0;
+- nvpb->cal_suffix1 = req.suffix1;
+- nvdev->base.vm_vram_size = req.vram_available;
+- nvdev->base.vm_gart_size = req.gart_available;
++ if (ret == -EAGAIN)
++ goto restart_cal;
++ nvpb->cal_suffix0 = req.suffix0;
++ nvpb->cal_suffix1 = req.suffix1;
++ if (!nvpb->no_aper_update) {
++ nvdev->base.vm_vram_size = req.vram_available;
++ nvdev->base.vm_gart_size = req.gart_available;
++ }
++ } else {
++ struct drm_nouveau_gem_pushbuf req;
++
Reply to: