Module: Mesa Branch: main Commit: 5089a758dfb1760a0dc397b0f491c4a6dc2160af URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=5089a758dfb1760a0dc397b0f491c4a6dc2160af
Author: Boris Brezillon <boris.brezil...@collabora.com> Date: Mon Nov 20 17:50:27 2023 +0100 panfrost: Back panfrost_bo with pan_kmod_bo object We keep the existing implementation unchanged but use pan_kmod for all interactions with the kernel driver. Signed-off-by: Boris Brezillon <boris.brezil...@collabora.com> Reviewed-by: Erik Faye-Lund <erik.faye-l...@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26357> --- src/panfrost/lib/pan_bo.c | 199 +++++++++++++++++++++------------------------- src/panfrost/lib/pan_bo.h | 14 ++-- 2 files changed, 97 insertions(+), 116 deletions(-) diff --git a/src/panfrost/lib/pan_bo.c b/src/panfrost/lib/pan_bo.c index a9587aa3422..19dba01d73b 100644 --- a/src/panfrost/lib/pan_bo.c +++ b/src/panfrost/lib/pan_bo.c @@ -28,7 +28,6 @@ #include <pthread.h> #include <stdio.h> #include <xf86drm.h> -#include "drm-uapi/panfrost_drm.h" #include "pan_bo.h" #include "pan_device.h" @@ -55,35 +54,55 @@ * around the linked list. */ +static uint32_t +to_kmod_bo_flags(uint32_t flags) +{ + uint32_t kmod_bo_flags = 0; + + if (flags & PAN_BO_EXECUTE) + kmod_bo_flags |= PAN_KMOD_BO_FLAG_EXECUTABLE; + if (flags & PAN_BO_GROWABLE) + kmod_bo_flags |= PAN_KMOD_BO_FLAG_ALLOC_ON_FAULT; + if (flags & PAN_BO_INVISIBLE) + kmod_bo_flags |= PAN_KMOD_BO_FLAG_NO_MMAP; + + return kmod_bo_flags; +} + static struct panfrost_bo * panfrost_bo_alloc(struct panfrost_device *dev, size_t size, uint32_t flags, const char *label) { - struct drm_panfrost_create_bo create_bo = {.size = size}; + struct pan_kmod_bo *kmod_bo; struct panfrost_bo *bo; - int ret; - - if (panfrost_device_kmod_version_major(dev) > 1 || - panfrost_device_kmod_version_minor(dev) >= 1) { - if (flags & PAN_BO_GROWABLE) - create_bo.flags |= PANFROST_BO_HEAP; - if (!(flags & PAN_BO_EXECUTE)) - create_bo.flags |= PANFROST_BO_NOEXEC; - } - ret = drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANFROST_CREATE_BO, - &create_bo); - if (ret) { - fprintf(stderr, "DRM_IOCTL_PANFROST_CREATE_BO failed: %m\n"); - return NULL; - } + kmod_bo = + pan_kmod_bo_alloc(dev->kmod.dev, NULL, size, to_kmod_bo_flags(flags)); + assert(kmod_bo); - bo = pan_lookup_bo(dev, create_bo.handle); + bo = pan_lookup_bo(dev, kmod_bo->handle); assert(!memcmp(bo, &((struct panfrost_bo){}), sizeof(*bo))); + bo->kmod_bo = kmod_bo; + + struct pan_kmod_vm_op vm_op = { + .type = PAN_KMOD_VM_OP_TYPE_MAP, + .va = + { + .start = PAN_KMOD_VM_MAP_AUTO_VA, + .size = bo->kmod_bo->size, + }, + .map = + { + .bo = bo->kmod_bo, + .bo_offset = 0, + }, + }; - bo->size = create_bo.size; - bo->ptr.gpu = create_bo.offset; - bo->gem_handle = create_bo.handle; + ASSERTED int ret = + pan_kmod_vm_bind(dev->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &vm_op, 1); + assert(!ret); + + bo->ptr.gpu = vm_op.va.start; bo->flags = flags; bo->dev = dev; bo->label = label; @@ -93,18 +112,27 @@ panfrost_bo_alloc(struct panfrost_device *dev, size_t size, uint32_t flags, static void panfrost_bo_free(struct panfrost_bo *bo) { - struct drm_gem_close gem_close = {.handle = panfrost_bo_handle(bo)}; - int fd = panfrost_device_fd(bo->dev); - int ret; + struct pan_kmod_bo *kmod_bo = bo->kmod_bo; + struct pan_kmod_vm *vm = bo->dev->kmod.vm; + uint64_t gpu_va = bo->ptr.gpu; /* BO will be freed with the sparse array, but zero to indicate free */ memset(bo, 0, sizeof(*bo)); - ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close); - if (ret) { - fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %m\n"); - assert(0); - } + struct pan_kmod_vm_op vm_op = { + .type = PAN_KMOD_VM_OP_TYPE_UNMAP, + .va = + { + .start = gpu_va, + .size = kmod_bo->size, + }, + }; + + ASSERTED int ret = pan_kmod_vm_bind( + vm, PAN_KMOD_VM_OP_MODE_DEFER_TO_NEXT_IDLE_POINT, &vm_op, 1); + assert(!ret); + + pan_kmod_bo_put(kmod_bo); } /* Returns true if the BO is ready, false otherwise. @@ -115,12 +143,6 @@ panfrost_bo_free(struct panfrost_bo *bo) bool panfrost_bo_wait(struct panfrost_bo *bo, int64_t timeout_ns, bool wait_readers) { - struct drm_panfrost_wait_bo req = { - .handle = panfrost_bo_handle(bo), - .timeout_ns = timeout_ns, - }; - int ret; - /* If the BO has been exported or imported we can't rely on the cached * state, we need to call the WAIT_BO ioctl. */ @@ -136,12 +158,7 @@ panfrost_bo_wait(struct panfrost_bo *bo, int64_t timeout_ns, bool wait_readers) return true; } - /* The ioctl returns >= 0 value when the BO we are waiting for is ready - * -1 otherwise. - */ - ret = - drmIoctl(panfrost_device_fd(bo->dev), DRM_IOCTL_PANFROST_WAIT_BO, &req); - if (ret != -1) { + if (pan_kmod_bo_wait(bo->kmod_bo, timeout_ns, !wait_readers)) { /* Set gpu_access to 0 so that the next call to bo_wait() * doesn't have to call the WAIT_BO ioctl. */ @@ -149,10 +166,6 @@ panfrost_bo_wait(struct panfrost_bo *bo, int64_t timeout_ns, bool wait_readers) return true; } - /* If errno is not ETIMEDOUT or EBUSY that means the handle we passed - * is invalid, which shouldn't happen here. - */ - assert(errno == ETIMEDOUT || errno == EBUSY); return false; } @@ -200,22 +213,14 @@ panfrost_bo_cache_fetch(struct panfrost_device *dev, size_t size, /* If the oldest BO in the cache is busy, likely so is * everything newer, so bail. */ - if (!panfrost_bo_wait(entry, dontwait ? 0 : INT64_MAX, PAN_BO_ACCESS_RW)) + if (!panfrost_bo_wait(entry, dontwait ? 0 : INT64_MAX, true)) break; - struct drm_panfrost_madvise madv = { - .handle = panfrost_bo_handle(entry), - .madv = PANFROST_MADV_WILLNEED, - }; - int ret; - /* This one works, splice it out of the cache */ list_del(&entry->bucket_link); list_del(&entry->lru_link); - ret = - drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANFROST_MADVISE, &madv); - if (!ret && !madv.retained) { + if (!pan_kmod_bo_make_unevictable(entry->kmod_bo)) { panfrost_bo_free(entry); continue; } @@ -269,14 +274,9 @@ panfrost_bo_cache_put(struct panfrost_bo *bo) pthread_mutex_lock(&dev->bo_cache.lock); struct list_head *bucket = pan_bucket(dev, MAX2(panfrost_bo_size(bo), 4096)); - struct drm_panfrost_madvise madv; struct timespec time; - madv.handle = panfrost_bo_handle(bo); - madv.madv = PANFROST_MADV_DONTNEED; - madv.retained = 0; - - drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANFROST_MADVISE, &madv); + pan_kmod_bo_make_evictable(bo->kmod_bo); /* Add us to the bucket */ list_addtail(&bo->bucket_link, bucket); @@ -324,28 +324,15 @@ panfrost_bo_cache_evict_all(struct panfrost_device *dev) void panfrost_bo_mmap(struct panfrost_bo *bo) { - struct drm_panfrost_mmap_bo mmap_bo = {.handle = panfrost_bo_handle(bo)}; - int ret; - if (bo->ptr.cpu) return; - ret = drmIoctl(panfrost_device_fd(bo->dev), DRM_IOCTL_PANFROST_MMAP_BO, - &mmap_bo); - if (ret) { - fprintf(stderr, "DRM_IOCTL_PANFROST_MMAP_BO failed: %m\n"); - assert(0); - } - - bo->ptr.cpu = - os_mmap(NULL, panfrost_bo_size(bo), PROT_READ | PROT_WRITE, MAP_SHARED, - panfrost_device_fd(bo->dev), mmap_bo.offset); + bo->ptr.cpu = pan_kmod_bo_mmap(bo->kmod_bo, 0, panfrost_bo_size(bo), + PROT_READ | PROT_WRITE, MAP_SHARED, NULL); if (bo->ptr.cpu == MAP_FAILED) { bo->ptr.cpu = NULL; - fprintf(stderr, - "mmap failed: result=%p size=0x%llx fd=%i offset=0x%llx %m\n", - bo->ptr.cpu, (long long)panfrost_bo_size(bo), - panfrost_device_fd(bo->dev), (long long)mmap_bo.offset); + fprintf(stderr, "mmap failed: result=%p size=0x%llx\n", bo->ptr.cpu, + (long long)panfrost_bo_size(bo)); } } @@ -468,38 +455,39 @@ struct panfrost_bo * panfrost_bo_import(struct panfrost_device *dev, int fd) { struct panfrost_bo *bo; - struct drm_panfrost_get_bo_offset get_bo_offset = { - 0, - }; ASSERTED int ret; unsigned gem_handle; pthread_mutex_lock(&dev->bo_map_lock); - - ret = drmPrimeFDToHandle(panfrost_device_fd(dev), fd, &gem_handle); + ret = drmPrimeFDToHandle(dev->kmod.dev->fd, fd, &gem_handle); assert(!ret); bo = pan_lookup_bo(dev, gem_handle); if (!bo->dev) { - get_bo_offset.handle = gem_handle; - ret = drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANFROST_GET_BO_OFFSET, - &get_bo_offset); + bo->dev = dev; + bo->kmod_bo = pan_kmod_bo_import(dev->kmod.dev, fd, 0); + + struct pan_kmod_vm_op vm_op = { + .type = PAN_KMOD_VM_OP_TYPE_MAP, + .va = + { + .start = PAN_KMOD_VM_MAP_AUTO_VA, + .size = bo->kmod_bo->size, + }, + .map = + { + .bo = bo->kmod_bo, + .bo_offset = 0, + }, + }; + + ASSERTED int ret = pan_kmod_vm_bind( + dev->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &vm_op, 1); assert(!ret); - bo->dev = dev; - bo->ptr.gpu = (mali_ptr)get_bo_offset.offset; - bo->size = lseek(fd, 0, SEEK_END); - /* Sometimes this can fail and return -1. size of -1 is not - * a nice thing for mmap to try mmap. Be more robust also - * for zero sized maps and fail nicely too - */ - if ((panfrost_bo_size(bo) == 0) || (panfrost_bo_size(bo) == (size_t)-1)) { - pthread_mutex_unlock(&dev->bo_map_lock); - return NULL; - } + bo->ptr.gpu = vm_op.va.start; bo->flags = PAN_BO_SHARED; - bo->gem_handle = gem_handle; p_atomic_set(&bo->refcnt, 1); } else { /* bo->refcnt == 0 can happen if the BO @@ -525,16 +513,9 @@ panfrost_bo_import(struct panfrost_device *dev, int fd) int panfrost_bo_export(struct panfrost_bo *bo) { - struct drm_prime_handle args = { - .handle = panfrost_bo_handle(bo), - .flags = DRM_CLOEXEC, - }; - - int ret = drmIoctl(panfrost_device_fd(bo->dev), DRM_IOCTL_PRIME_HANDLE_TO_FD, - &args); - if (ret == -1) - return -1; + int ret = pan_kmod_bo_export(bo->kmod_bo); + if (ret >= 0) + bo->flags |= PAN_BO_SHARED; - bo->flags |= PAN_BO_SHARED; - return args.fd; + return ret; } diff --git a/src/panfrost/lib/pan_bo.h b/src/panfrost/lib/pan_bo.h index 2f0940e3755..24414998368 100644 --- a/src/panfrost/lib/pan_bo.h +++ b/src/panfrost/lib/pan_bo.h @@ -30,6 +30,8 @@ #include "util/list.h" #include "panfrost-job.h" +#include "kmod/pan_kmod.h" + /* Flags for allocated memory */ /* This memory region is executable */ @@ -95,16 +97,14 @@ struct panfrost_bo { /* Atomic reference count */ int32_t refcnt; + /* Kernel representation of a buffer object. */ + struct pan_kmod_bo *kmod_bo; + struct panfrost_device *dev; /* Mapping for the entire object (all levels) */ struct panfrost_ptr ptr; - /* Size of all entire trees */ - size_t size; - - int gem_handle; - uint32_t flags; /* Combination of PAN_BO_ACCESS_{READ,WRITE} flags encoding pending @@ -120,13 +120,13 @@ struct panfrost_bo { static inline size_t panfrost_bo_size(struct panfrost_bo *bo) { - return bo->size; + return bo->kmod_bo->size; } static inline size_t panfrost_bo_handle(struct panfrost_bo *bo) { - return bo->gem_handle; + return bo->kmod_bo->handle; } bool panfrost_bo_wait(struct panfrost_bo *bo, int64_t timeout_ns,