.gitignore | 2 ChangeLog | 469 Makefile.am | 6 configure.ac | 40 debian/changelog | 53 debian/patches/03_revert_abi_change.diff | 1220 ++ debian/patches/03_update_nouveau_defines_1.diff | 1620 -- debian/patches/04_update_nouveau_defines_2.diff | 4032 ------- debian/patches/05_update_nouveau_defines_3.diff | 117 debian/patches/06_nouveau_free_objects_on_channel_close.diff | 78 debian/patches/07_nouveau_fix_mem_leak_on_channel_free.diff | 28 debian/patches/08_nouveau_no_flush_notify_on_channel_free.diff | 22 debian/patches/09_add_BEGIN_RING_NI.diff | 25 debian/patches/series | 8 include/drm/Makefile.am | 5 include/drm/nouveau_drm.h | 87 include/drm/vmwgfx_drm.h | 574 + intel/intel_atomic.h | 15 intel/intel_bufmgr_fake.c | 5 intel/intel_bufmgr_gem.c | 27 intel/libdrm_intel.pc.in | 3 libkms/Makefile.am | 29 libkms/api.c | 138 libkms/intel.c | 240 libkms/internal.h | 71 libkms/libkms.h | 74 libkms/libkms.pc.in | 10 libkms/linux.c | 215 libkms/vmwgfx.c | 207 nouveau/Makefile.am | 6 nouveau/nouveau_bo.c | 83 nouveau/nouveau_bo.h | 14 nouveau/nouveau_channel.c | 12 nouveau/nouveau_channel.h | 5 nouveau/nouveau_class.h | 5408 +++++----- nouveau/nouveau_device.c | 8 nouveau/nouveau_private.h | 15 nouveau/nouveau_pushbuf.c | 385 nouveau/nouveau_pushbuf.h | 34 nouveau/nouveau_reloc.c | 132 nouveau/nouveau_reloc.h | 32 nouveau/nouveau_resource.c | 9 nouveau/nouveau_resource.h | 3 radeon/libdrm_radeon.pc.in | 2 radeon/radeon_bo.c | 60 radeon/radeon_bo.h | 24 radeon/radeon_bo_gem.c | 32 radeon/radeon_bo_gem.h | 8 radeon/radeon_bo_int.h | 4 radeon/radeon_cs.c | 38 radeon/radeon_cs.h | 48 radeon/radeon_cs_gem.c | 153 radeon/radeon_cs_gem.h | 8 radeon/radeon_cs_space.c | 170 tests/Makefile.am | 4 tests/dristat.c | 3 tests/drmstat.c | 10 tests/drmtest.c | 4 tests/kmstest/Makefile.am | 17 tests/kmstest/main.c | 90 tests/modeprint/modeprint.c | 8 tests/modetest/modetest.c | 38 xf86drmMode.c | 129 xf86drmMode.h | 2 xf86drmSL.c | 3 65 files changed, 7246 insertions(+), 9175 deletions(-)
New commits: commit ed306d4f575b18b8f0981fee2e23ca06d577af94 Author: Timo Aaltonen <[email protected]> Date: Fri Feb 19 14:19:17 2010 +0200 Release 2.4.18-1ubuntu1 diff --git a/debian/changelog b/debian/changelog index aed09ba..2692d93 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,11 @@ -libdrm (2.4.18-1ubuntu1) UNRELEASED; urgency=low +libdrm (2.4.18-1ubuntu1) lucid; urgency=low * Merge from Debian unstable. * Remove the nouveau patches, since they are included in this version. * Add 03_revert_abi_change.diff to revert the nouveau ABI change. We need the old ABI until the kernel has been updated. - -- Timo Aaltonen <[email protected]> Fri, 19 Feb 2010 14:14:45 +0200 + -- Timo Aaltonen <[email protected]> Fri, 19 Feb 2010 14:19:08 +0200 libdrm (2.4.18-1) unstable; urgency=low commit 16a75483cd4ae1a2282a76eabe7f97252b4a4906 Author: Timo Aaltonen <[email protected]> Date: Fri Feb 19 14:19:02 2010 +0200 Merge from Debian unstable. * Remove the nouveau patches, since they are included in this version. * Add 03_revert_abi_change.diff to revert the nouveau ABI change. We need the old ABI until the kernel has been updated. diff --git a/debian/changelog b/debian/changelog index af2807e..aed09ba 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +libdrm (2.4.18-1ubuntu1) UNRELEASED; urgency=low + + * Merge from Debian unstable. + * Remove the nouveau patches, since they are included in this version. + * Add 03_revert_abi_change.diff to revert the nouveau ABI change. + We need the old ABI until the kernel has been updated. + + -- Timo Aaltonen <[email protected]> Fri, 19 Feb 2010 14:14:45 +0200 + libdrm (2.4.18-1) unstable; urgency=low * New upstream release. diff --git a/debian/patches/03_revert_abi_change.diff b/debian/patches/03_revert_abi_change.diff new file mode 100644 index 0000000..d91d8e5 --- /dev/null +++ b/debian/patches/03_revert_abi_change.diff @@ -0,0 +1,1220 @@ +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; ++ ++ if (pbbo->presumed_ok == 0) { ++ nvbo->domain = pbbo->presumed_domain; ++ nvbo->offset = pbbo->presumed_offset; ++ } + +- for (i = 0; i < nvpb->nr_push; i++) +- nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index); ++ nvbo->pending = NULL; ++ nouveau_bo_ref(NULL, &bo); ++ } + + nvpb->nr_buffers = 0; + nvpb->nr_relocs = 0; +- nvpb->nr_push = 0; + + /* Allocate space for next push buffer */ + assert(!nouveau_pushbuf_space(chan, min)); +@@ -275,7 +273,7 @@ nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min) + if (chan->flush_notify) + chan->flush_notify(chan); + +- nvpb->marker = NULL; ++ nvpb->marker = 0; + return ret; + } + +@@ -283,7 +281,7 @@ int + nouveau_pushbuf_marker_emit(struct nouveau_channel *chan, + unsigned wait_dwords, unsigned wait_relocs) + { +- struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb; ++ struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf); + + if (AVAIL_RING(chan) < wait_dwords) + return nouveau_pushbuf_flush(chan, wait_dwords); +@@ -291,9 +289,7 @@ nouveau_pushbuf_marker_emit(struct nouveau_channel *chan, + if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS) + return nouveau_pushbuf_flush(chan, wait_dwords); + +- nvpb->marker = chan->cur; +- nvpb->marker_offset = nvpb->current_offset; +- nvpb->marker_push = nvpb->nr_push; ++ nvpb->marker = nvpb->base.cur - nvpb->pushbuf; + nvpb->marker_relocs = nvpb->nr_relocs; + return 0; + } +@@ -301,7 +297,7 @@ nouveau_pushbuf_marker_emit(struct nouveau_channel *chan, + void + nouveau_pushbuf_marker_undo(struct nouveau_channel *chan) + { +- struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb; ++ struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf); + unsigned i; + + if (!nvpb->marker) +@@ -309,19 +305,49 @@ nouveau_pushbuf_marker_undo(struct nouveau_channel *chan) + + /* undo any relocs/buffers added to the list since last marker */ + for (i = nvpb->marker_relocs; 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; ++ ++ nvbo->pending = NULL; ++ nouveau_bo_ref(NULL, &bo); ++ nvpb->nr_buffers--; + } + nvpb->nr_relocs = nvpb->marker_relocs; + +- for (i = nvpb->marker_push; i < nvpb->nr_push; i++) +- nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index); +- nvpb->nr_push = nvpb->marker_push; +- + /* reset pushbuf back to last marker */ +- chan->cur = nvpb->marker; +- nvpb->current_offset = nvpb->marker_offset; +- nvpb->marker = NULL; ++ nvpb->base.cur = nvpb->pushbuf + nvpb->marker; ++ nvpb->base.remaining = nvpb->size - nvpb->marker; ++ nvpb->marker = 0; ++} ++ ++static uint32_t ++nouveau_pushbuf_calc_reloc(struct drm_nouveau_gem_pushbuf_bo *pbbo, ++ struct drm_nouveau_gem_pushbuf_reloc *r) ++{ ++ uint32_t push = 0; ++ ++ if (r->flags & NOUVEAU_GEM_RELOC_LOW) ++ push = (pbbo->presumed_offset + r->data); ++ else ++ if (r->flags & NOUVEAU_GEM_RELOC_HIGH) ++ push = (pbbo->presumed_offset + r->data) >> 32; ++ else ++ push = r->data; ++ ++ if (r->flags & NOUVEAU_GEM_RELOC_OR) { ++ if (pbbo->presumed_domain & NOUVEAU_GEM_DOMAIN_VRAM) ++ push |= r->vor; ++ else -- To UNSUBSCRIBE, email to [email protected] with a subject of "unsubscribe". Trouble? Contact [email protected] Archive: http://lists.debian.org/[email protected]

