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

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: