diff --git a/src/panfrost/lib/kmod/pan_kmod.h b/src/panfrost/lib/kmod/pan_kmod.h index 735e2e1518c..4482928e374 100644 --- a/src/panfrost/lib/kmod/pan_kmod.h +++ b/src/panfrost/lib/kmod/pan_kmod.h @@ -179,6 +179,12 @@ struct pan_kmod_dev_props { /* AFBC feature bits. */ uint32_t afbc_features; + + /* Support cycle count and timestamp propagation as job requirement */ + bool gpu_can_query_timestamp; + + /* GPU Timestamp frequency */ + uint64_t timestamp_frequency; }; /* Memory allocator for kmod internal allocations. */ @@ -404,6 +410,9 @@ struct pan_kmod_ops { * usable. */ enum pan_kmod_vm_state (*vm_query_state)(struct pan_kmod_vm *vm); + + /* Query the current GPU timestamp */ + uint64_t (*query_timestamp)(const struct pan_kmod_dev *dev); }; /* KMD information. */ @@ -640,6 +649,12 @@ pan_kmod_vm_handle(struct pan_kmod_vm *vm) return vm->handle; } +static inline uint64_t +pan_kmod_query_timestamp(const struct pan_kmod_dev *dev) +{ + return dev->ops->query_timestamp(dev); +} + #if defined(__cplusplus) } // extern "C" #endif diff --git a/src/panfrost/lib/kmod/panfrost_kmod.c b/src/panfrost/lib/kmod/panfrost_kmod.c index 58cbcc5cb65..d6004882932 100644 --- a/src/panfrost/lib/kmod/panfrost_kmod.c +++ b/src/panfrost/lib/kmod/panfrost_kmod.c @@ -201,6 +201,12 @@ panfrost_dev_query_props(const struct pan_kmod_dev *dev, panfrost_query_raw(fd, DRM_PANFROST_PARAM_AFBC_FEATURES, true, 0); panfrost_dev_query_thread_props(dev, props); + + if (dev->driver.version.major > 1 || dev->driver.version.minor >= 3) { + props->gpu_can_query_timestamp = true; + props->timestamp_frequency = panfrost_query_raw( + fd, DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP_FREQUENCY, true, 0); + } } static uint32_t @@ -460,6 +466,13 @@ panfrost_kmod_vm_bind(struct pan_kmod_vm *vm, enum pan_kmod_vm_op_mode mode, return 0; } +static uint64_t +panfrost_kmod_query_timestamp(const struct pan_kmod_dev *dev) +{ + return panfrost_query_raw(dev->fd, DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP, + false, 0); +} + const struct pan_kmod_ops panfrost_kmod_ops = { .dev_create = panfrost_kmod_dev_create, .dev_destroy = panfrost_kmod_dev_destroy, @@ -475,4 +488,5 @@ const struct pan_kmod_ops panfrost_kmod_ops = { .vm_create = panfrost_kmod_vm_create, .vm_destroy = panfrost_kmod_vm_destroy, .vm_bind = panfrost_kmod_vm_bind, + .query_timestamp = panfrost_kmod_query_timestamp, }; diff --git a/src/panfrost/lib/kmod/panthor_kmod.c b/src/panfrost/lib/kmod/panthor_kmod.c index 22a08091336..b461d056aca 100644 --- a/src/panfrost/lib/kmod/panthor_kmod.c +++ b/src/panfrost/lib/kmod/panthor_kmod.c @@ -80,6 +80,7 @@ struct panthor_kmod_dev { struct { struct drm_panthor_gpu_info gpu; struct drm_panthor_csif_info csif; + struct drm_panthor_timestamp_info timestamp; } props; }; @@ -133,6 +134,20 @@ panthor_kmod_dev_create(int fd, uint32_t flags, drmVersionPtr version, goto err_free_dev; } + if (version->version_major > 1 || version->version_minor >= 1) { + query = (struct drm_panthor_dev_query){ + .type = DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO, + .size = sizeof(panthor_dev->props.timestamp), + .pointer = (uint64_t)(uintptr_t)&panthor_dev->props.timestamp, + }; + + ret = drmIoctl(fd, DRM_IOCTL_PANTHOR_DEV_QUERY, &query); + if (ret) { + mesa_loge("DRM_IOCTL_PANTHOR_DEV_QUERY failed (err=%d)", errno); + goto err_free_dev; + } + } + /* Map the LATEST_FLUSH_ID register at device creation time. */ panthor_dev->flush_id = os_mmap(0, getpagesize(), PROT_READ, MAP_SHARED, fd, DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET); @@ -203,6 +218,11 @@ panthor_dev_query_props(const struct pan_kmod_dev *dev, /* This register does not exist because AFBC is no longer optional. */ .afbc_features = 0, + + /* Access to timstamp from the GPU is always supported on Panthor. */ + .gpu_can_query_timestamp = true, + + .timestamp_frequency = panthor_dev->props.timestamp.timestamp_frequency, }; static_assert(sizeof(props->texture_features) == @@ -1086,6 +1106,29 @@ panthor_kmod_get_csif_props(const struct pan_kmod_dev *dev) return &panthor_dev->props.csif; } +static uint64_t +panthor_kmod_query_timestamp(const struct pan_kmod_dev *dev) +{ + if (dev->driver.version.major <= 1 && dev->driver.version.minor < 1) + return 0; + + struct drm_panthor_timestamp_info timestamp_info; + + struct drm_panthor_dev_query query = (struct drm_panthor_dev_query){ + .type = DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO, + .size = sizeof(timestamp_info), + .pointer = (uint64_t)(uintptr_t)×tamp_info, + }; + + int ret = drmIoctl(dev->fd, DRM_IOCTL_PANTHOR_DEV_QUERY, &query); + if (ret) { + mesa_loge("DRM_IOCTL_PANTHOR_DEV_QUERY failed (err=%d)", errno); + return 0; + } + + return timestamp_info.current_timestamp; +} + const struct pan_kmod_ops panthor_kmod_ops = { .dev_create = panthor_kmod_dev_create, .dev_destroy = panthor_kmod_dev_destroy, @@ -1101,4 +1144,5 @@ const struct pan_kmod_ops panthor_kmod_ops = { .vm_destroy = panthor_kmod_vm_destroy, .vm_bind = panthor_kmod_vm_bind, .vm_query_state = panthor_kmod_vm_query_state, + .query_timestamp = panthor_kmod_query_timestamp, };