diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 90937fff602..0b6b8746ad7 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -1,273 +1,3 @@ -// kgsl_pipe.c -#include "freedreno/drm/kgsl/kgsl_priv.h" -#include "freedreno/drm/freedreno_ringbuffer_sp.h" - -/* TODO this function is borrowed from turnip, can it be shared in some way? */ -int -kgsl_pipe_safe_ioctl(int fd, unsigned long request, void *arg) -{ - int ret; - - do { - ret = ioctl(fd, request, arg); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - - return ret; -} - -/* TODO this function is borrowed from turnip, can it be shared in some way? - * safe_ioctl is not enough as restarted waits would not adjust the timeout - * which could lead to waiting substantially longer than requested - */ -static int -wait_timestamp_safe(int fd, - unsigned int context_id, - unsigned int timestamp, - int64_t timeout_ms) -{ - int64_t start_time = os_time_get_nano(); - struct kgsl_device_waittimestamp_ctxtid wait = { - .context_id = context_id, - .timestamp = timestamp, - .timeout = timeout_ms, - }; - - while (true) { - int ret = kgsl_pipe_safe_ioctl(fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, &wait); - - if (ret == -1 && (errno == EINTR || errno == EAGAIN)) { - int64_t current_time = os_time_get_nano(); - - /* update timeout to consider time that has passed since the start */ - timeout_ms -= (current_time - start_time) / 1000000; - if (timeout_ms <= 0) { - errno = ETIME; - return -1; - } - - wait.timeout = (unsigned int) timeout_ms; - start_time = current_time; - } else { - return ret; - } - } -} - -int -kgsl_get_prop(int fd, unsigned int type, void *value, size_t size) -{ - struct kgsl_device_getproperty getprop = { - .type = type, - .value = value, - .sizebytes = size, - }; - - return kgsl_pipe_safe_ioctl(fd, IOCTL_KGSL_DEVICE_GETPROPERTY, &getprop); -} - -static int -kgsl_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, - uint64_t *value) -{ - struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); - switch (param) { - case FD_DEVICE_ID: - case FD_GPU_ID: - *value = kgsl_pipe->dev_id.gpu_id; - return 0; - case FD_GMEM_SIZE: - *value = kgsl_pipe->gmem_size; - return 0; - case FD_GMEM_BASE: - *value = kgsl_pipe->gmem_base; - return 0; - case FD_CHIP_ID: - *value = kgsl_pipe->dev_id.chip_id; - return 0; - case FD_NR_PRIORITIES: - /* Take from kgsl kmd source code, if device is a4xx or newer - * it has KGSL_PRIORITY_MAX_RB_LEVELS=4 priorities otherwise it just has one. - * https://android.googlesource.com/kernel/msm/+/refs/tags/android-13.0.0_r0.21/drivers/gpu/msm/kgsl.h#56 - */ - *value = kgsl_pipe->dev_id.gpu_id >= 400 ? 4 : 1; - return 0; - case FD_MAX_FREQ: - /* Explicity fault on MAX_FREQ as we don't have a way to convert - * timestamp values from KGSL into time values. If we use the default - * path an error message would be generated when this is simply an - * unsupported feature. - */ - return -1; - default: - ERROR_MSG("invalid param id: %d", param); - return -1; - } -} - -static int -kgsl_pipe_set_param(struct fd_pipe *pipe, uint32_t param, uint64_t value) -{ - ERROR_MSG("kgsl_pipe_set_param not implemented"); - return -1; -} - -static int -kgsl_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence, uint64_t timeout) -{ - struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); - return wait_timestamp_safe(pipe->dev->fd, kgsl_pipe->queue_id, fence->kfence, timeout); -} - -static void -kgsl_pipe_destroy(struct fd_pipe *pipe) -{ - struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); - struct kgsl_drawctxt_destroy req = { - .drawctxt_id = kgsl_pipe->queue_id, - }; - - fd_pipe_sp_ringpool_fini(pipe); - kgsl_pipe_safe_ioctl(pipe->dev->fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &req); - free(kgsl_pipe); -} - -static int -kgsl_reset_status(struct fd_pipe *pipe, enum fd_reset_status *status) -{ - struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); - uint32_t value = kgsl_pipe->queue_id; - int ret = kgsl_get_prop(pipe->dev->fd, KGSL_PROP_GPU_RESET_STAT, &value, sizeof(value)); - - if (!ret) { - switch (value) { - case KGSL_CTX_STAT_NO_ERROR: - *status = FD_RESET_NO_ERROR; - break; - case KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT: - *status = FD_RESET_GUILTY; - break; - case KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT: - *status = FD_RESET_INNOCENT; - break; - case KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT: - default: - *status = FD_RESET_UNKNOWN; - break; - } - } - - return ret; -} - -static const struct fd_pipe_funcs pipe_funcs = { - .ringbuffer_new_object = fd_ringbuffer_sp_new_object, - .submit_new = kgsl_submit_sp_new, - .reset_status = kgsl_reset_status, - .flush = fd_pipe_sp_flush, - .wait = kgsl_pipe_wait, - .get_param = kgsl_pipe_get_param, - .set_param = kgsl_pipe_set_param, - .destroy = kgsl_pipe_destroy, -}; - -struct fd_pipe *kgsl_pipe_new(struct fd_device *dev, enum fd_pipe_id id, - uint32_t prio) -{ - struct kgsl_pipe *kgsl_pipe = NULL; - struct fd_pipe *pipe = NULL; - kgsl_pipe = calloc(1, sizeof(*kgsl_pipe)); - if (!kgsl_pipe) { - ERROR_MSG("allocation failed"); - goto fail; - } - - pipe = &kgsl_pipe->base; - pipe->dev = dev; - pipe->funcs = &pipe_funcs; - - struct kgsl_devinfo info; - if(kgsl_get_prop(dev->fd, KGSL_PROP_DEVICE_INFO, &info, sizeof(info))) - goto fail; - - uint64_t gmem_iova; - if(kgsl_get_prop(dev->fd, KGSL_PROP_UCHE_GMEM_VADDR, &gmem_iova, sizeof(gmem_iova))) - goto fail; - - kgsl_pipe->dev_id.gpu_id = - ((info.chip_id >> 24) & 0xff) * 100 + - ((info.chip_id >> 16) & 0xff) * 10 + - ((info.chip_id >> 8) & 0xff); - - kgsl_pipe->dev_id.chip_id = info.chip_id; - kgsl_pipe->gmem_size = info.gmem_sizebytes; - kgsl_pipe->gmem_base = gmem_iova; - - struct kgsl_drawctxt_create req = { - .flags = KGSL_CONTEXT_SAVE_GMEM | - KGSL_CONTEXT_NO_GMEM_ALLOC | - KGSL_CONTEXT_PREAMBLE, - }; - - int ret = kgsl_pipe_safe_ioctl(dev->fd, IOCTL_KGSL_DRAWCTXT_CREATE, &req); - if(ret) - goto fail; - - kgsl_pipe->queue_id = req.drawctxt_id; - - fd_pipe_sp_ringpool_init(pipe); - - return pipe; -fail: - if (pipe) - fd_pipe_del(pipe); - return NULL; -} - - -static const struct fd_device_funcs funcs = { - .bo_new = kgsl_bo_new, - .pipe_new = kgsl_pipe_new, - .bo_from_handle = kgsl_bo_from_handle, - .bo_from_dmabuf = kgsl_bo_from_dmabuf, - .bo_close_handle = kgsl_bo_close_handle, - .destroy = kgsl_device_destroy, -}; - -struct fd_device * -kgsl_device_new(int fd) -{ - struct kgsl_device *kgsl_dev; - struct fd_device *dev; - struct kgsl_devinfo info; - - /* Try to read the device info to detect if the FD is really KGSL */ - if(kgsl_get_prop(fd, KGSL_PROP_DEVICE_INFO, &info, sizeof(info))) - return NULL; - - kgsl_dev = calloc(1, sizeof(*kgsl_dev)); - if (!kgsl_dev) - return NULL; - - dev = &kgsl_dev->base; - dev->funcs = &funcs; - dev->fd = fd; - dev->version = FD_VERSION_ROBUSTNESS; - dev->features = FD_FEATURE_DIRECT_RESET | FD_FEATURE_IMPORT_DMABUF; - - /* async submit_queue used for softpin deffered submits */ - util_queue_init(&dev->submit_queue, "sq", 8, 1, 0, NULL); - - dev->bo_size = sizeof(struct kgsl_bo); - - return dev; -} - -static void -kgsl_device_destroy(struct fd_device *dev) -{ -} - - /* * Copyright (C) 2012 Rob Clark * @@ -403,7 +133,7 @@ fd_screen_get_timestamp(struct pipe_screen *pscreen) if (screen->has_timestamp) { uint64_t n; - kgsl_pipe_get_param(screen->pipe, FD_TIMESTAMP, &n); + fd_pipe_get_param(screen->pipe, FD_TIMESTAMP, &n); assert(screen->max_freq > 0); return n * 1000000000 / screen->max_freq; } else { @@ -822,7 +552,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) if (fd_device_version(screen->dev) >= FD_VERSION_VA_SIZE) { uint64_t va_size; - if (!kgsl_pipe_get_param(screen->pipe, FD_VA_SIZE, &va_size)) { + if (!fd_pipe_get_param(screen->pipe, FD_VA_SIZE, &va_size)) { system_memory = MIN2(system_memory, va_size); } } @@ -1278,7 +1008,7 @@ fd_screen_create(int fd, const struct pipe_screen_config *config, struct renderonly *ro) { - struct fd_device *dev = kgsl_device_new(fd); + struct fd_device *dev = fd_device_new(fd); if (!dev) return NULL; @@ -1304,20 +1034,20 @@ fd_screen_create(int fd, // maybe this should be in context? printf("Initializing pipe\n"); - screen->pipe = kgsl_pipe_new(screen->dev, FD_PIPE_3D, 0); + screen->pipe = fd_pipe_new(screen->dev, FD_PIPE_3D, 0); if (!screen->pipe) { printf("could not create 3d pipe\n"); goto fail; } - if (kgsl_pipe_get_param(screen->pipe, FD_GMEM_SIZE, &val)) { + if (fd_pipe_get_param(screen->pipe, FD_GMEM_SIZE, &val)) { printf("could not get GMEM size\n"); goto fail; } screen->gmemsize_bytes = debug_get_num_option("FD_MESA_GMEM", val); if (fd_device_version(dev) >= FD_VERSION_GMEM_BASE) { - kgsl_pipe_get_param(screen->pipe, FD_GMEM_BASE, &screen->gmem_base); + fd_pipe_get_param(screen->pipe, FD_GMEM_BASE, &screen->gmem_base); } printf("setting max freq\n"); @@ -1327,14 +1057,14 @@ fd_screen_create(int fd, screen->dev_id = fd_pipe_dev_id(screen->pipe); printf("dev id pipe done\n"); printf("get gpu id\n"); - if (kgsl_pipe_get_param(screen->pipe, FD_GPU_ID, &val)) { + if (fd_pipe_get_param(screen->pipe, FD_GPU_ID, &val)) { printf("could not get gpu-id\n"); goto fail; } screen->gpu_id = val; printf("get chip id\n"); - if (kgsl_pipe_get_param(screen->pipe, FD_CHIP_ID, &val)) { + if (fd_pipe_get_param(screen->pipe, FD_CHIP_ID, &val)) { printf("could not get chip-id\n"); /* older kernels may not have this property: */ unsigned core = screen->gpu_id / 100; @@ -1349,7 +1079,7 @@ fd_screen_create(int fd, printf("piping gen\n"); screen->gen = fd_dev_gen(screen->dev_id); printf("get rings\n"); - if (kgsl_pipe_get_param(screen->pipe, FD_NR_PRIORITIES, &val)) { + if (fd_pipe_get_param(screen->pipe, FD_NR_PRIORITIES, &val)) { printf("could not get # of rings\n"); screen->priority_mask = 0; } else {