amdgpu/amdgpu.h | 5 + amdgpu/amdgpu_device.c | 33 +++++++- amdgpu/amdgpu_internal.h | 13 +-- amdgpu/amdgpu_vamgr.c | 63 +++++++-------- configure.ac | 2 debian/changelog | 7 + debian/libdrm-freedreno1.symbols | 1 debian/rules | 2 freedreno/freedreno-symbol-check | 1 freedreno/freedreno_drmif.h | 3 freedreno/freedreno_pipe.c | 8 +- freedreno/freedreno_priv.h | 2 freedreno/kgsl/kgsl_pipe.c | 3 freedreno/msm/msm_bo.c | 6 - freedreno/msm/msm_pipe.c | 5 - freedreno/msm/msm_priv.h | 21 ++++- freedreno/msm/msm_ringbuffer.c | 155 +++++++++++++++++++++++++-------------- tests/amdgpu/amdgpu_test.c | 5 + tests/amdgpu/basic_tests.c | 5 + tests/amdgpu/bo_tests.c | 5 + tests/amdgpu/cs_tests.c | 5 + tests/amdgpu/vce_tests.c | 6 + tests/modetest/modetest.c | 94 ++++++++++++++++++++--- xf86drmMode.c | 12 --- 24 files changed, 326 insertions(+), 136 deletions(-)
New commits: commit 50949b57acc5860b036410683b69a98e12e3fffc Author: Robert Hooker <sarv...@ubuntu.com> Date: Tue Aug 18 16:40:35 2015 -0400 Bump symbols and shlibs for freedreno diff --git a/debian/changelog b/debian/changelog index c1df6aa..e9214e1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ libdrm (2.4.64-1) UNRELEASED; urgency=medium * New upstream release. + * Bump symbols file and shlibs for libdrm-freedreno1. -- Robert Hooker <sarv...@ubuntu.com> Tue, 18 Aug 2015 16:05:01 -0400 diff --git a/debian/libdrm-freedreno1.symbols b/debian/libdrm-freedreno1.symbols index b7602f9..efb91a9 100644 --- a/debian/libdrm-freedreno1.symbols +++ b/debian/libdrm-freedreno1.symbols @@ -21,6 +21,7 @@ libdrm_freedreno.so.1 libdrm-freedreno1 #MINVER# fd_pipe_get_param@Base 0 fd_pipe_new@Base 0 fd_pipe_wait@Base 0 + fd_pipe_wait_timeout@Base 2.4.64 fd_ringbuffer_del@Base 0 fd_ringbuffer_emit_reloc_ring@Base 0 fd_ringbuffer_flush@Base 0 diff --git a/debian/rules b/debian/rules index ec465df..dee3894 100755 --- a/debian/rules +++ b/debian/rules @@ -106,7 +106,7 @@ endif dh_makeshlibs -plibdrm-radeon1 -V'libdrm-radeon1 (>= 2.4.39)' -- -c4 ifeq ($(ARM), yes) dh_makeshlibs -plibdrm-omap1 -V'libdrm-omap1 (>= 2.4.38)' -- -c4 - dh_makeshlibs -plibdrm-freedreno1 -V'libdrm-freedreno1 (>= 2.4.57)' -- -c4 + dh_makeshlibs -plibdrm-freedreno1 -V'libdrm-freedreno1 (>= 2.4.64)' -- -c4 dh_makeshlibs -plibdrm-exynos1 -V'libdrm-exynos1 (>= 2.4.60)' -- -c4 dh_makeshlibs -plibdrm-tegra0 -V'libdrm-tegra0' -- -c4 endif commit 564ab8aa8535474c295406154c1626529b518da4 Author: Robert Hooker <sarv...@ubuntu.com> Date: Tue Aug 18 16:38:41 2015 -0400 Bump changelog. diff --git a/debian/changelog b/debian/changelog index 6f71a39..c1df6aa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +libdrm (2.4.64-1) UNRELEASED; urgency=medium + + * New upstream release. + + -- Robert Hooker <sarv...@ubuntu.com> Tue, 18 Aug 2015 16:05:01 -0400 + libdrm (2.4.63-1) unstable; urgency=medium [ Robert Hooker ] commit ab2fadabde3829b1ec56bd4756165dd9bd281488 Author: Rob Clark <robcl...@freedesktop.org> Date: Tue Aug 18 11:56:50 2015 -0400 Bump version for release Signed-off-by: Rob Clark <robcl...@freedesktop.org> diff --git a/configure.ac b/configure.ac index e2a2f16..f07507b 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ([2.63]) AC_INIT([libdrm], - [2.4.63], + [2.4.64], [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI], [libdrm]) commit 04a118d800280c88aed5cb4a5f29fdfb5a38e36b Author: Rob Clark <robcl...@freedesktop.org> Date: Tue Aug 18 10:53:36 2015 -0400 freedreno: update freedreno-symbol-check Signed-off-by: Rob Clark <robcl...@freedesktop.org> diff --git a/freedreno/freedreno-symbol-check b/freedreno/freedreno-symbol-check index 7115448..e593df4 100755 --- a/freedreno/freedreno-symbol-check +++ b/freedreno/freedreno-symbol-check @@ -32,6 +32,7 @@ fd_pipe_del fd_pipe_get_param fd_pipe_new fd_pipe_wait +fd_pipe_wait_timeout fd_ringbuffer_del fd_ringbuffer_emit_reloc_ring fd_ringbuffer_flush commit 5e5a3c48b83fb3929e57cb4e7261624a327137f3 Author: Thierry Reding <tred...@nvidia.com> Date: Wed Apr 9 09:00:49 2014 +0200 libdrm: Make indentation consistent Use tabs and spaces consistently to align function arguments on subsequent lines with those of the first line. Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com> Signed-off-by: Thierry Reding <tred...@nvidia.com> diff --git a/xf86drmMode.c b/xf86drmMode.c index 23348d7..9b70ce8 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -249,7 +249,7 @@ err_allocs: } int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, - uint8_t bpp, uint32_t pitch, uint32_t bo_handle, + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id) { struct drm_mode_fb_cmd f; @@ -374,7 +374,7 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) } int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, - uint32_t x, uint32_t y, uint32_t *connectors, int count, + uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode) { struct drm_mode_crtc crtc; commit d2d361cddd2bdf8f1bf627b9ebe8ca802156f8af Author: Thierry Reding <tred...@nvidia.com> Date: Wed Apr 9 08:59:04 2014 +0200 libdrm: Remove gratuitous blank lines Usage of blank lines can be a matter of taste, of course, but for these we can surely all agree that they're not needed and inconsistent. Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com> Signed-off-by: Thierry Reding <tred...@nvidia.com> diff --git a/xf86drmMode.c b/xf86drmMode.c index fc19504..23348d7 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -114,7 +114,6 @@ void drmModeFreeResources(drmModeResPtr ptr) drmFree(ptr->connectors); drmFree(ptr->encoders); drmFree(ptr); - } void drmModeFreeFB(drmModeFBPtr ptr) @@ -132,7 +131,6 @@ void drmModeFreeCrtc(drmModeCrtcPtr ptr) return; drmFree(ptr); - } void drmModeFreeConnector(drmModeConnectorPtr ptr) @@ -145,7 +143,6 @@ void drmModeFreeConnector(drmModeConnectorPtr ptr) drmFree(ptr->props); drmFree(ptr->modes); drmFree(ptr); - } void drmModeFreeEncoder(drmModeEncoderPtr ptr) @@ -340,7 +337,6 @@ int drmModeDirtyFB(int fd, uint32_t bufferId, return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); } - /* * Crtc functions */ @@ -377,7 +373,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) return r; } - int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode) @@ -610,7 +605,6 @@ int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); } - drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) { struct drm_mode_get_property prop; @@ -944,7 +938,6 @@ int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, uint32_t crtc_w, uint32_t crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) - { struct drm_mode_set_plane s; @@ -965,7 +958,6 @@ int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s); } - drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) { struct drm_mode_get_plane ovr, counts; commit 56d8dd6a9c03680700e0b0043cb56e0af7e3e3de Author: Jammy Zhou <jammy.z...@amd.com> Date: Mon Aug 17 11:09:09 2015 +0800 amdgpu: make vamgr per device v2 Each device can have its own vamgr, so make it per device now. This can fix the failure with multiple GPUs used in one single process. v2: rebase Signed-off-by: Jammy Zhou <jammy.z...@amd.com> Reviewed-by: Christian König <christian.koe...@amd.com> diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c index e16cd24..75b12e2 100644 --- a/amdgpu/amdgpu_device.c +++ b/amdgpu/amdgpu_device.c @@ -130,7 +130,8 @@ static int amdgpu_get_auth(int fd, int *auth) static void amdgpu_device_free_internal(amdgpu_device_handle dev) { - amdgpu_vamgr_reference(&dev->vamgr, NULL); + amdgpu_vamgr_deinit(dev->vamgr); + free(dev->vamgr); util_hash_table_destroy(dev->bo_flink_names); util_hash_table_destroy(dev->bo_handles); pthread_mutex_destroy(&dev->bo_table_mutex); @@ -251,7 +252,13 @@ int amdgpu_device_initialize(int fd, if (r) goto cleanup; - dev->vamgr = amdgpu_vamgr_get_global(dev); + dev->vamgr = calloc(1, sizeof(struct amdgpu_bo_va_mgr)); + if (dev->vamgr == NULL) + goto cleanup; + + amdgpu_vamgr_init(dev->vamgr, dev->dev_info.virtual_address_offset, + dev->dev_info.virtual_address_max, + dev->dev_info.virtual_address_alignment); max = MIN2(dev->dev_info.virtual_address_max, 0xffffffff); start = amdgpu_vamgr_find_va(dev->vamgr, @@ -278,6 +285,8 @@ free_va: r = -ENOMEM; amdgpu_vamgr_free_va(dev->vamgr, start, max - dev->dev_info.virtual_address_offset); + amdgpu_vamgr_deinit(dev->vamgr); + free(dev->vamgr); cleanup: if (dev->fd >= 0) diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h index 3ce0969..5d86603 100644 --- a/amdgpu/amdgpu_internal.h +++ b/amdgpu/amdgpu_internal.h @@ -52,7 +52,6 @@ struct amdgpu_bo_va_hole { }; struct amdgpu_bo_va_mgr { - atomic_t refcount; /* the start virtual address */ uint64_t va_offset; uint64_t va_max; @@ -125,13 +124,6 @@ struct amdgpu_context { drm_private void amdgpu_bo_free_internal(amdgpu_bo_handle bo); -drm_private struct amdgpu_bo_va_mgr* -amdgpu_vamgr_get_global(struct amdgpu_device *dev); - -drm_private void -amdgpu_vamgr_reference(struct amdgpu_bo_va_mgr **dst, - struct amdgpu_bo_va_mgr *src); - drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, uint64_t max, uint64_t alignment); diff --git a/amdgpu/amdgpu_vamgr.c b/amdgpu/amdgpu_vamgr.c index 507a73a..04d2881 100644 --- a/amdgpu/amdgpu_vamgr.c +++ b/amdgpu/amdgpu_vamgr.c @@ -33,8 +33,6 @@ #include "amdgpu_internal.h" #include "util_math.h" -static struct amdgpu_bo_va_mgr vamgr = {{0}}; - int amdgpu_va_range_query(amdgpu_device_handle dev, enum amdgpu_gpu_va_range type, uint64_t *start, uint64_t *end) { @@ -67,28 +65,6 @@ drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) pthread_mutex_destroy(&mgr->bo_va_mutex); } -drm_private struct amdgpu_bo_va_mgr * -amdgpu_vamgr_get_global(struct amdgpu_device *dev) -{ - int ref; - ref = atomic_inc_return(&vamgr.refcount); - - if (ref == 1) - amdgpu_vamgr_init(&vamgr, dev->dev_info.virtual_address_offset, - dev->dev_info.virtual_address_max, - dev->dev_info.virtual_address_alignment); - return &vamgr; -} - -drm_private void -amdgpu_vamgr_reference(struct amdgpu_bo_va_mgr **dst, - struct amdgpu_bo_va_mgr *src) -{ - if (update_references(&(*dst)->refcount, NULL)) - amdgpu_vamgr_deinit(*dst); - *dst = src; -} - drm_private uint64_t amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, uint64_t alignment, uint64_t base_required) @@ -105,7 +81,7 @@ amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, pthread_mutex_lock(&mgr->bo_va_mutex); /* TODO: using more appropriate way to track the holes */ /* first look for a hole */ - LIST_FOR_EACH_ENTRY_SAFE(hole, n, &vamgr.va_holes, list) { + LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) { if (base_required) { if(hole->offset > base_required || (hole->offset + hole->size) < (base_required + size)) commit ffa305d0fc926418e4dff432381ead8907dc18d9 Author: Jammy Zhou <jammy.z...@amd.com> Date: Mon Aug 17 11:09:08 2015 +0800 amdgpu: add flag to support 32bit VA address v4 The AMDGPU_VA_RANGE_32_BIT flag is added to request VA range in the 32bit address space for amdgpu_va_range_alloc. The 32bit address space is reserved at initialization time, and managed with a separate VAMGR as part of the global VAMGR. And if no enough VA space available in range above 4GB, this reserved range can be used as fallback. v2: add comment for AMDGPU_VA_RANGE_32_BIT, and add vamgr to va_range v3: rebase to Emil's drm_private series v4: fix one warning Signed-off-by: Jammy Zhou <jammy.z...@amd.com> Reviewed-by: Christian König <christian.koe...@amd.com> diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h index a3eea84..e44d802 100644 --- a/amdgpu/amdgpu.h +++ b/amdgpu/amdgpu.h @@ -1075,6 +1075,11 @@ int amdgpu_read_mm_registers(amdgpu_device_handle dev, unsigned dword_offset, uint32_t *values); /** + * Flag to request VA address range in the 32bit address space +*/ +#define AMDGPU_VA_RANGE_32_BIT 0x1 + +/** * Allocate virtual address range * * \param dev - [in] Device handle. See #amdgpu_device_initialize() diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c index c6bbae8..e16cd24 100644 --- a/amdgpu/amdgpu_device.c +++ b/amdgpu/amdgpu_device.c @@ -43,6 +43,7 @@ #include "amdgpu_drm.h" #include "amdgpu_internal.h" #include "util_hash_table.h" +#include "util_math.h" #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) #define UINT_TO_PTR(x) ((void *)((intptr_t)(x))) @@ -173,6 +174,7 @@ int amdgpu_device_initialize(int fd, int flag_auth = 0; int flag_authexist=0; uint32_t accel_working = 0; + uint64_t start, max; *device_handle = NULL; @@ -251,6 +253,19 @@ int amdgpu_device_initialize(int fd, dev->vamgr = amdgpu_vamgr_get_global(dev); + max = MIN2(dev->dev_info.virtual_address_max, 0xffffffff); + start = amdgpu_vamgr_find_va(dev->vamgr, + max - dev->dev_info.virtual_address_offset, + dev->dev_info.virtual_address_alignment, 0); + if (start > 0xffffffff) + goto free_va; /* shouldn't get here */ + + dev->vamgr_32 = calloc(1, sizeof(struct amdgpu_bo_va_mgr)); + if (dev->vamgr_32 == NULL) + goto free_va; + amdgpu_vamgr_init(dev->vamgr_32, start, max, + dev->dev_info.virtual_address_alignment); + *major_version = dev->major_version; *minor_version = dev->minor_version; *device_handle = dev; @@ -259,6 +274,11 @@ int amdgpu_device_initialize(int fd, return 0; +free_va: + r = -ENOMEM; + amdgpu_vamgr_free_va(dev->vamgr, start, + max - dev->dev_info.virtual_address_offset); + cleanup: if (dev->fd >= 0) close(dev->fd); diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h index 4b07aff..3ce0969 100644 --- a/amdgpu/amdgpu_internal.h +++ b/amdgpu/amdgpu_internal.h @@ -66,6 +66,7 @@ struct amdgpu_va { uint64_t address; uint64_t size; enum amdgpu_gpu_va_range range; + struct amdgpu_bo_va_mgr *vamgr; }; struct amdgpu_device { @@ -83,7 +84,10 @@ struct amdgpu_device { pthread_mutex_t bo_table_mutex; struct drm_amdgpu_info_device dev_info; struct amdgpu_gpu_info info; + /** The global VA manager for the whole virtual address space */ struct amdgpu_bo_va_mgr *vamgr; + /** The VA manager for the 32bit address space */ + struct amdgpu_bo_va_mgr *vamgr_32; }; struct amdgpu_bo { @@ -128,6 +132,11 @@ drm_private void amdgpu_vamgr_reference(struct amdgpu_bo_va_mgr **dst, struct amdgpu_bo_va_mgr *src); +drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, + uint64_t max, uint64_t alignment); + +drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr); + drm_private uint64_t amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, uint64_t alignment, uint64_t base_required); diff --git a/amdgpu/amdgpu_vamgr.c b/amdgpu/amdgpu_vamgr.c index eef8a71..507a73a 100644 --- a/amdgpu/amdgpu_vamgr.c +++ b/amdgpu/amdgpu_vamgr.c @@ -46,7 +46,7 @@ int amdgpu_va_range_query(amdgpu_device_handle dev, return -EINVAL; } -static void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, +drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, uint64_t max, uint64_t alignment) { mgr->va_offset = start; @@ -57,7 +57,7 @@ static void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, pthread_mutex_init(&mgr->bo_va_mutex, NULL); } -static void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) +drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) { struct amdgpu_bo_va_hole *hole; LIST_FOR_EACH_ENTRY(hole, &mgr->va_holes, list) { @@ -255,23 +255,39 @@ int amdgpu_va_range_alloc(amdgpu_device_handle dev, amdgpu_va_handle *va_range_handle, uint64_t flags) { - va_base_alignment = MAX2(va_base_alignment, dev->vamgr->va_alignment); - size = ALIGN(size, vamgr.va_alignment); + struct amdgpu_bo_va_mgr *vamgr; - *va_base_allocated = amdgpu_vamgr_find_va(dev->vamgr, size, + if (flags & AMDGPU_VA_RANGE_32_BIT) + vamgr = dev->vamgr_32; + else + vamgr = dev->vamgr; + + va_base_alignment = MAX2(va_base_alignment, vamgr->va_alignment); + size = ALIGN(size, vamgr->va_alignment); + + *va_base_allocated = amdgpu_vamgr_find_va(vamgr, size, + va_base_alignment, va_base_required); + + if (!(flags & AMDGPU_VA_RANGE_32_BIT) && + (*va_base_allocated == AMDGPU_INVALID_VA_ADDRESS)) { + /* fallback to 32bit address */ + vamgr = dev->vamgr_32; + *va_base_allocated = amdgpu_vamgr_find_va(vamgr, size, va_base_alignment, va_base_required); + } if (*va_base_allocated != AMDGPU_INVALID_VA_ADDRESS) { struct amdgpu_va* va; va = calloc(1, sizeof(struct amdgpu_va)); if(!va){ - amdgpu_vamgr_free_va(dev->vamgr, *va_base_allocated, size); + amdgpu_vamgr_free_va(vamgr, *va_base_allocated, size); return -ENOMEM; } va->dev = dev; va->address = *va_base_allocated; va->size = size; va->range = va_range_type; + va->vamgr = vamgr; *va_range_handle = va; } else { return -EINVAL; @@ -284,7 +300,9 @@ int amdgpu_va_range_free(amdgpu_va_handle va_range_handle) { if(!va_range_handle || !va_range_handle->address) return 0; - amdgpu_vamgr_free_va(va_range_handle->dev->vamgr, va_range_handle->address, + + amdgpu_vamgr_free_va(va_range_handle->vamgr, + va_range_handle->address, va_range_handle->size); free(va_range_handle); return 0; commit 102ab6f0049c2c85857fd19f098bc5b51e2a8a60 Author: Jammy Zhou <jammy.z...@amd.com> Date: Mon Aug 17 11:09:07 2015 +0800 amdgpu: improve amdgpu_vamgr_init Make it a generic function independent of the device info. Signed-off-by: Jammy Zhou <jammy.z...@amd.com> Reviewed-by: Christian König <christian.koe...@amd.com> diff --git a/amdgpu/amdgpu_vamgr.c b/amdgpu/amdgpu_vamgr.c index b5d330f..eef8a71 100644 --- a/amdgpu/amdgpu_vamgr.c +++ b/amdgpu/amdgpu_vamgr.c @@ -46,11 +46,12 @@ int amdgpu_va_range_query(amdgpu_device_handle dev, return -EINVAL; } -static void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, struct amdgpu_device *dev) +static void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, + uint64_t max, uint64_t alignment) { - mgr->va_offset = dev->dev_info.virtual_address_offset; - mgr->va_max = dev->dev_info.virtual_address_max; - mgr->va_alignment = dev->dev_info.virtual_address_alignment; + mgr->va_offset = start; + mgr->va_max = max; + mgr->va_alignment = alignment; list_inithead(&mgr->va_holes); pthread_mutex_init(&mgr->bo_va_mutex, NULL); @@ -73,7 +74,9 @@ amdgpu_vamgr_get_global(struct amdgpu_device *dev) ref = atomic_inc_return(&vamgr.refcount); if (ref == 1) - amdgpu_vamgr_init(&vamgr, dev); + amdgpu_vamgr_init(&vamgr, dev->dev_info.virtual_address_offset, + dev->dev_info.virtual_address_max, + dev->dev_info.virtual_address_alignment); return &vamgr; } commit 15ba8768f7002d220002d424790ff2e89310c07f Author: Rob Clark <robcl...@freedesktop.org> Date: Mon Aug 17 10:33:59 2015 -0400 freedreno: add fd_pipe_wait_timeout() We need to pass through a timeout parameter to implement pipe->fence_finish() properly. Signed-off-by: Rob Clark <robcl...@freedesktop.org> diff --git a/freedreno/freedreno_drmif.h b/freedreno/freedreno_drmif.h index 88fc03d..81a14b4 100644 --- a/freedreno/freedreno_drmif.h +++ b/freedreno/freedreno_drmif.h @@ -86,6 +86,9 @@ void fd_pipe_del(struct fd_pipe *pipe); int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value); int fd_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp); +/* timeout in nanosec */ +int fd_pipe_wait_timeout(struct fd_pipe *pipe, uint32_t timestamp, + uint64_t timeout); /* buffer-object functions: diff --git a/freedreno/freedreno_pipe.c b/freedreno/freedreno_pipe.c index b6fed0a..4a756d7 100644 --- a/freedreno/freedreno_pipe.c +++ b/freedreno/freedreno_pipe.c @@ -72,5 +72,11 @@ int fd_pipe_get_param(struct fd_pipe *pipe, int fd_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp) { - return pipe->funcs->wait(pipe, timestamp); + return fd_pipe_wait_timeout(pipe, timestamp, ~0); +} + +int fd_pipe_wait_timeout(struct fd_pipe *pipe, uint32_t timestamp, + uint64_t timeout) +{ + return pipe->funcs->wait(pipe, timestamp, timeout); } diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h index cb24780..1dddcc3 100644 --- a/freedreno/freedreno_priv.h +++ b/freedreno/freedreno_priv.h @@ -100,7 +100,7 @@ drm_private void fd_device_del_locked(struct fd_device *dev); struct fd_pipe_funcs { struct fd_ringbuffer * (*ringbuffer_new)(struct fd_pipe *pipe, uint32_t size); int (*get_param)(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value); - int (*wait)(struct fd_pipe *pipe, uint32_t timestamp); + int (*wait)(struct fd_pipe *pipe, uint32_t timestamp, uint64_t timeout); void (*destroy)(struct fd_pipe *pipe); }; diff --git a/freedreno/kgsl/kgsl_pipe.c b/freedreno/kgsl/kgsl_pipe.c index 08c87a6..e2fd65c 100644 --- a/freedreno/kgsl/kgsl_pipe.c +++ b/freedreno/kgsl/kgsl_pipe.c @@ -56,7 +56,8 @@ static int kgsl_pipe_get_param(struct fd_pipe *pipe, } } -static int kgsl_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp) +static int kgsl_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp, + uint64_t timeout) { struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); struct kgsl_device_waittimestamp req = { diff --git a/freedreno/msm/msm_bo.c b/freedreno/msm/msm_bo.c index 6dc3776..fd94413 100644 --- a/freedreno/msm/msm_bo.c +++ b/freedreno/msm/msm_bo.c @@ -75,7 +75,7 @@ static int msm_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op) .op = op, }; - get_abs_timeout(&req.timeout, 5000); + get_abs_timeout(&req.timeout, 5000000000); return drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_CPU_PREP, &req, sizeof(req)); } diff --git a/freedreno/msm/msm_pipe.c b/freedreno/msm/msm_pipe.c index ddc975e..e1edffe 100644 --- a/freedreno/msm/msm_pipe.c +++ b/freedreno/msm/msm_pipe.c @@ -54,7 +54,8 @@ static int msm_pipe_get_param(struct fd_pipe *pipe, } } -static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp) +static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp, + uint64_t timeout) { struct fd_device *dev = pipe->dev; struct drm_msm_wait_fence req = { @@ -62,7 +63,7 @@ static int msm_pipe_wait(struct fd_pipe *pipe, uint32_t timestamp) }; int ret; - get_abs_timeout(&req.timeout, 5000); + get_abs_timeout(&req.timeout, timeout); ret = drmCommandWrite(dev->fd, DRM_MSM_WAIT_FENCE, &req, sizeof(req)); if (ret) { diff --git a/freedreno/msm/msm_priv.h b/freedreno/msm/msm_priv.h index 637cb52..e499b3b 100644 --- a/freedreno/msm/msm_priv.h +++ b/freedreno/msm/msm_priv.h @@ -96,13 +96,13 @@ drm_private int msm_bo_new_handle(struct fd_device *dev, drm_private struct fd_bo * msm_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle); -static inline void get_abs_timeout(struct drm_msm_timespec *tv, uint32_t ms) +static inline void get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns) { struct timespec t; - uint32_t s = ms / 1000; + uint32_t s = ns / 1000000000; clock_gettime(CLOCK_MONOTONIC, &t); tv->tv_sec = t.tv_sec + s; - tv->tv_nsec = t.tv_nsec + ((ms - (s * 1000)) * 1000000); + tv->tv_nsec = t.tv_nsec + ns - (s * 1000000000); } #endif /* MSM_PRIV_H_ */ commit 4413f191a051847c53a6150df199d35a106b6cf4 Author: Rob Clark <robcl...@freedesktop.org> Date: Tue Jul 21 12:55:29 2015 -0400 freedreno/msm: dump out submit info on error User should only see these with LIBGL_DEBUG=verbose. But in case you are hitting issues like "handle X at index Y already on submit list" errors from the kernel, this gives some useful visibility for debug. Signed-off-by: Rob Clark <robcl...@freedesktop.org> diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index 842574e..5ddea57 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -31,6 +31,7 @@ #endif #include <assert.h> +#include <inttypes.h> #include "freedreno_ringbuffer.h" #include "msm_priv.h" @@ -228,7 +229,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start struct drm_msm_gem_submit req = { .pipe = to_msm_pipe(ring->pipe)->pipe, }; - uint32_t i, submit_offset, size; + uint32_t i, j, submit_offset, size; int ret; submit_offset = offset_bytes(last_start, ring->start); @@ -258,6 +259,23 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start &req, sizeof(req)); if (ret) { ERROR_MSG("submit failed: %d (%s)", ret, strerror(errno)); + ERROR_MSG(" pipe: %u", req.pipe); + for (i = 0; i < msm_ring->submit.nr_bos; i++) { + struct drm_msm_gem_submit_bo *bo = &msm_ring->submit.bos[i]; + ERROR_MSG(" bos[%d]: handle=%u, flags=%x", i, bo->handle, bo->flags); + } + for (i = 0; i < msm_ring->submit.nr_cmds; i++) { + struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; + struct drm_msm_gem_submit_reloc *relocs = U642VOID(cmd->relocs); + ERROR_MSG(" cmd[%d]: type=%u, submit_idx=%u, submit_offset=%u, size=%u\n", + i, cmd->type, cmd->submit_idx, cmd->submit_offset, cmd->size); + for (j = 0; j < cmd->nr_relocs; j++) { + struct drm_msm_gem_submit_reloc *r = &relocs[j]; + ERROR_MSG(" reloc[%d]: submit_offset=%u, or=%08x, shift=%d, reloc_idx=%u" + ", reloc_offset=%"PRIu64, j, r->submit_offset, r->or, r->shift, + r->reloc_idx, r->reloc_offset); + } + } } else { /* update timestamp on all rings associated with submit: */ for (i = 0; i < msm_ring->submit.nr_cmds; i++) { commit 9e34ee4f75ef559ff3a3c6d4b8f285453eea1f29 Author: Rob Clark <robcl...@freedesktop.org> Date: Tue Jul 21 11:57:00 2015 -0400 freedreno/msm: fix issue where same bo is on multiple rings It should be a less common case, but it is possible for a single bo to be on multiple rings, for example when sharing a buffer across multiple pipe_context's created from same pipe_screen. So rather than completely fall over in this case, fallback to slow-path of looping over all bo's in the ring's bo-table (but retain the fast- path of constant-lookup for the first ring the buffer is on). Signed-off-by: Rob Clark <robcl...@freedesktop.org> diff --git a/freedreno/msm/msm_bo.c b/freedreno/msm/msm_bo.c index 3f5b6d0..6dc3776 100644 --- a/freedreno/msm/msm_bo.c +++ b/freedreno/msm/msm_bo.c @@ -129,7 +129,6 @@ drm_private struct fd_bo * msm_bo_from_handle(struct fd_device *dev, { struct msm_bo *msm_bo; struct fd_bo *bo; - unsigned i; msm_bo = calloc(1, sizeof(*msm_bo)); if (!msm_bo) @@ -139,8 +138,5 @@ drm_private struct fd_bo * msm_bo_from_handle(struct fd_device *dev, bo->funcs = &funcs; bo->fd = -1; - for (i = 0; i < ARRAY_SIZE(msm_bo->list); i++) - list_inithead(&msm_bo->list[i]); - return bo; } diff --git a/freedreno/msm/msm_priv.h b/freedreno/msm/msm_priv.h index 94d2357..637cb52 100644 --- a/freedreno/msm/msm_priv.h +++ b/freedreno/msm/msm_priv.h @@ -71,8 +71,19 @@ struct msm_bo { struct fd_bo base; uint64_t offset; uint64_t presumed; - uint32_t indexp1[FD_PIPE_MAX]; /* index plus 1 */ - struct list_head list[FD_PIPE_MAX]; + /* in the common case, a bo won't be referenced by more than a single + * (parent) ring[*]. So to avoid looping over all the bo's in the + * reloc table to find the idx of a bo that might already be in the + * table, we cache the idx in the bo. But in order to detect the + * slow-path where bo is ref'd in multiple rb's, we also must track + * the current_ring for which the idx is valid. See bo2idx(). + * + * [*] in case multiple ringbuffers, ie. one toplevel and other rb(s) + * used for IB target(s), the toplevel rb is the parent which is + * tracking bo's for the submit + */ + struct fd_ringbuffer *current_ring; + uint32_t idx; }; static inline struct msm_bo * to_msm_bo(struct fd_bo *x) diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index 2798c3f..842574e 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -39,8 +39,6 @@ struct msm_ringbuffer { struct fd_ringbuffer base; struct fd_bo *ring_bo; - struct list_head submit_list; - /* submit ioctl related tables: */ struct { /* bo's table: */ @@ -56,11 +54,17 @@ struct msm_ringbuffer { uint32_t nr_relocs, max_relocs; } submit; + /* should have matching entries in submit.bos: */ + struct fd_bo **bos; + uint32_t nr_bos, max_bos; + /* should have matching entries in submit.cmds: */ struct fd_ringbuffer **rings; uint32_t nr_rings, max_rings; }; +static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER; + static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz) { if ((nr + 1) > *max) { @@ -83,27 +87,47 @@ static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x) return (struct msm_ringbuffer *)x; } +static uint32_t append_bo(struct fd_ringbuffer *ring, struct fd_bo *bo) +{ + struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); + uint32_t idx; + + idx = APPEND(&msm_ring->submit, bos); + idx = APPEND(msm_ring, bos); + + msm_ring->submit.bos[idx].flags = 0; + msm_ring->submit.bos[idx].handle = bo->handle; + msm_ring->submit.bos[idx].presumed = to_msm_bo(bo)->presumed; + + msm_ring->bos[idx] = fd_bo_ref(bo); + + return idx; +} + /* add (if needed) bo, return idx: */ static uint32_t bo2idx(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t flags) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); struct msm_bo *msm_bo = to_msm_bo(bo); - int id = ring->pipe->id; uint32_t idx; - if (!msm_bo->indexp1[id]) { - struct list_head *list = &msm_bo->list[id]; - idx = APPEND(&msm_ring->submit, bos); - msm_ring->submit.bos[idx].flags = 0; - msm_ring->submit.bos[idx].handle = bo->handle; - msm_ring->submit.bos[idx].presumed = msm_bo->presumed; - msm_bo->indexp1[id] = idx + 1; - - assert(LIST_IS_EMPTY(list)); - fd_bo_ref(bo); - list_addtail(list, &msm_ring->submit_list); + pthread_mutex_lock(&idx_lock); + if (!msm_bo->current_ring) { + idx = append_bo(ring, bo); + msm_bo->current_ring = ring; + msm_bo->idx = idx; + } else if (msm_bo->current_ring == ring) { + idx = msm_bo->idx; } else { - idx = msm_bo->indexp1[id] - 1; + /* slow-path: */ + for (idx = 0; idx < msm_ring->nr_bos; idx++) + if (msm_ring->bos[idx] == bo) + break; + if (idx == msm_ring->nr_bos) { + /* not found */ + idx = append_bo(ring, bo); + } } + pthread_mutex_unlock(&idx_lock); if (flags & FD_RELOC_READ) msm_ring->submit.bos[idx].flags |= MSM_SUBMIT_BO_READ; if (flags & FD_RELOC_WRITE) @@ -193,6 +217,8 @@ static void flush_reset(struct fd_ringbuffer *ring) msm_ring->submit.nr_relocs = 0; msm_ring->submit.nr_cmds = 0; msm_ring->submit.nr_bos = 0; + msm_ring->nr_rings = 0; + msm_ring->nr_bos = 0; } static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start) @@ -202,9 +228,8 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start struct drm_msm_gem_submit req = { .pipe = to_msm_pipe(ring->pipe)->pipe, }; - struct msm_bo *msm_bo = NULL, *tmp; uint32_t i, submit_offset, size; - int ret, id = ring->pipe->id; + int ret; submit_offset = offset_bytes(last_start, ring->start); size = offset_bytes(ring->cur, last_start); @@ -242,10 +267,9 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start } } - LIST_FOR_EACH_ENTRY_SAFE(msm_bo, tmp, &msm_ring->submit_list, list[id]) { - struct list_head *list = &msm_bo->list[id]; - list_delinit(list); - msm_bo->indexp1[id] = 0; + for (i = 0; i < msm_ring->nr_bos; i++) { + struct msm_bo *msm_bo = to_msm_bo(msm_ring->bos[i]); + msm_bo->current_ring = NULL; fd_bo_del(&msm_bo->base);