Rebased ref, commits from common ancestor:
commit 197bdde16f9c405936f7a6cdce30322770022562
Author: Brice Goglin <bgog...@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 <bgog...@debian.org>  Wed, 24 Mar 2010 22:12:36 +0100
+ -- Brice Goglin <bgog...@debian.org>  Wed, 24 Mar 2010 22:27:00 +0100
 
 libdrm (2.4.18-3) unstable; urgency=low
 

commit 9f62499e2dd1df046001d174d9a6518b3db929e4
Author: Brice Goglin <bgog...@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 <bgog...@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# d...@base 2.4.4
+ nouveau_bo_b...@base 2.4.4
+ nouveau_bo_emit_buf...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_bo_f...@base 2.4.4
+ nouveau_bo_handle_...@base 2.4.4
+ nouveau_bo_handle_...@base 2.4.4
+ nouveau_bo_i...@base 2.4.4
+ nouveau_bo_...@base 2.4.4
+ nouveau_bo_map_fl...@base 2.4.11-1ubuntu1~
+ nouveau_bo_map_ra...@base 2.4.11-1ubuntu1~
+ nouveau_bo_...@base 2.4.4
+ nouveau_bo_new_t...@base 2.4.11-1ubuntu1~
+ nouveau_bo_pend...@base 2.4.16
+ nouveau_bo_...@base 2.4.4
+ nouveau_bo_...@base 2.4.4
+ nouveau_bo_taked...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_bo_t...@base 2.4.4
+ nouveau_bo_un...@base 2.4.4
+ nouveau_bo_un...@base 2.4.4
+ nouveau_bo_u...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_bo_validate_n...@base 2.4.4
+ nouveau_bo_w...@base 2.4.11-1ubuntu1~
+ nouveau_channel_al...@base 2.4.4
+ nouveau_channel_f...@base 2.4.4
+ nouveau_device_cl...@base 2.4.4
+ nouveau_device_get_pa...@base 2.4.4
+ nouveau_device_o...@base 2.4.4
+ nouveau_device_open_exist...@base 2.4.4
+ nouveau_device_set_pa...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_dma_channel_i...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_dma_kick...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_dma_w...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_e...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_fl...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_signal...@base 2.4.4
+#MISSING: 2.4.12+git20090729.5a73f066# nouveau_fence_w...@base 2.4.4
+ nouveau_grobj_al...@base 2.4.4
+ nouveau_grobj_autob...@base 2.4.4
+ nouveau_grobj_f...@base 2.4.4
+ nouveau_grobj_...@base 2.4.4
+ nouveau_notifier_al...@base 2.4.4
+ nouveau_notifier_f...@base 2.4.4
+ nouveau_notifier_re...@base 2.4.4
+ nouveau_notifier_return_...@base 2.4.4
+ nouveau_notifier_sta...@base 2.4.4
+ nouveau_notifier_wait_sta...@base 2.4.4
+ nouveau_pushbuf_emit_re...@base 2.4.4
+ nouveau_pushbuf_f...@base 2.4.17-1ubuntu1~
+ nouveau_pushbuf_fl...@base 2.4.4
+ nouveau_pushbuf_i...@base 2.4.4
+ nouveau_pushbuf_marker_e...@base 2.4.16
+ nouveau_pushbuf_marker_u...@base 2.4.16
+ nouveau_resource_al...@base 2.4.4
+ nouveau_resource_dest...@base 2.4.18
+ nouveau_resource_f...@base 2.4.4
+ nouveau_resource_i...@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 <bgog...@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 <bgog...@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;
++
++restart_push:
++              req.channel = chan->id;
++              req.nr_dwords = nvpb->size - nvpb->base.remaining;
++              req.dwords = (uint64_t)(unsigned long)nvpb->pushbuf;
++              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;
++              ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
++                                    &req, sizeof(req));
++              if (ret == -EAGAIN)
++                      goto restart_push;
++      }
++
+ 
+       /* Update presumed offset/domain for any buffers that moved.
+        * Dereference all buffers on validate list
+        */
+       for (i = 0; i < nvpb->nr_relocs; i++) {
+-              nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
+-              nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
+-      }
++              struct drm_nouveau_gem_pushbuf_reloc *r = &nvpb->relocs[i];
++              struct drm_nouveau_gem_pushbuf_bo *pbbo =
++                      &nvpb->buffers[r->bo_index];
++              struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
++              struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
++
++              if (--nvbo->pending_refcnt)
++                      continue;


-- 
To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: http://lists.debian.org/e1nuye3-0007t4...@alioth.debian.org

Reply via email to