drm/panthor: Add DEV_QUERY_TIMESTAMP_INFO dev query
Expose timestamp information supported by the GPU with a new device query. Mali uses an external timer as GPU system time. On ARM, this is wired to the generic arch timer so we wire cntfrq_el0 as device frequency. This new uAPI will be used in Mesa to implement timestamp queries and VK_KHR_calibrated_timestamps. Since this extends the uAPI and because userland needs a way to advertise those features conditionally, this also bumps the driver minor version. v2: - Rewrote to use GPU timestamp register - Added timestamp_offset to drm_panthor_timestamp_info - Add missing include for arch_timer_get_cntfrq - Rework commit message v3: - Add panthor_gpu_read_64bit_counter - Change panthor_gpu_read_timestamp to use panthor_gpu_read_64bit_counter v4: - Fix multiple typos in uAPI documentation - Mention behavior when the timestamp frequency is unknown - Use u64 instead of unsigned long long for panthor_gpu_read_timestamp - Apply r-b from Mihail Signed-off-by: Mary Guillemard <mary.guillemard@collabora.com> Reviewed-by: Mihail Atanassov <mihail.atanassov@arm.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240830080349.24736-2-mary.guillemard@collabora.com
This commit is contained in:
parent
a1c24630be
commit
a3d9738f24
4 changed files with 115 additions and 1 deletions
|
|
@ -3,6 +3,10 @@
|
|||
/* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */
|
||||
/* Copyright 2019 Collabora ltd. */
|
||||
|
||||
#ifdef CONFIG_ARM_ARCH_TIMER
|
||||
#include <asm/arch_timer.h>
|
||||
#endif
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
|
@ -164,6 +168,7 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride,
|
|||
_Generic(_obj_name, \
|
||||
PANTHOR_UOBJ_DECL(struct drm_panthor_gpu_info, tiler_present), \
|
||||
PANTHOR_UOBJ_DECL(struct drm_panthor_csif_info, pad), \
|
||||
PANTHOR_UOBJ_DECL(struct drm_panthor_timestamp_info, current_timestamp), \
|
||||
PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \
|
||||
PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \
|
||||
PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \
|
||||
|
|
@ -750,10 +755,33 @@ static void panthor_submit_ctx_cleanup(struct panthor_submit_ctx *ctx,
|
|||
kvfree(ctx->jobs);
|
||||
}
|
||||
|
||||
static int panthor_query_timestamp_info(struct panthor_device *ptdev,
|
||||
struct drm_panthor_timestamp_info *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(ptdev->base.dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_ARM_ARCH_TIMER
|
||||
arg->timestamp_frequency = arch_timer_get_cntfrq();
|
||||
#else
|
||||
arg->timestamp_frequency = 0;
|
||||
#endif
|
||||
arg->current_timestamp = panthor_gpu_read_timestamp(ptdev);
|
||||
arg->timestamp_offset = panthor_gpu_read_timestamp_offset(ptdev);
|
||||
|
||||
pm_runtime_put(ptdev->base.dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct drm_file *file)
|
||||
{
|
||||
struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
|
||||
struct drm_panthor_dev_query *args = data;
|
||||
struct drm_panthor_timestamp_info timestamp_info;
|
||||
int ret;
|
||||
|
||||
if (!args->pointer) {
|
||||
switch (args->type) {
|
||||
|
|
@ -765,6 +793,10 @@ static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct d
|
|||
args->size = sizeof(ptdev->csif_info);
|
||||
return 0;
|
||||
|
||||
case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO:
|
||||
args->size = sizeof(timestamp_info);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -777,6 +809,14 @@ static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct d
|
|||
case DRM_PANTHOR_DEV_QUERY_CSIF_INFO:
|
||||
return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info);
|
||||
|
||||
case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO:
|
||||
ret = panthor_query_timestamp_info(ptdev, ×tamp_info);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PANTHOR_UOBJ_SET(args->pointer, args->size, timestamp_info);
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1387,6 +1427,7 @@ static const struct file_operations panthor_drm_driver_fops = {
|
|||
/*
|
||||
* PanCSF driver version:
|
||||
* - 1.0 - initial interface
|
||||
* - 1.1 - adds DEV_QUERY_TIMESTAMP_INFO query
|
||||
*/
|
||||
static const struct drm_driver panthor_drm_driver = {
|
||||
.driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
|
||||
|
|
@ -1400,7 +1441,7 @@ static const struct drm_driver panthor_drm_driver = {
|
|||
.desc = "Panthor DRM driver",
|
||||
.date = "20230801",
|
||||
.major = 1,
|
||||
.minor = 0,
|
||||
.minor = 1,
|
||||
|
||||
.gem_create_object = panthor_gem_create_object,
|
||||
.gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
|
||||
|
|
|
|||
|
|
@ -480,3 +480,50 @@ void panthor_gpu_resume(struct panthor_device *ptdev)
|
|||
panthor_gpu_irq_resume(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK);
|
||||
panthor_gpu_l2_power_on(ptdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* panthor_gpu_read_64bit_counter() - Read a 64-bit counter at a given offset.
|
||||
* @ptdev: Device.
|
||||
* @reg: The offset of the register to read.
|
||||
*
|
||||
* Return: The counter value.
|
||||
*/
|
||||
static u64
|
||||
panthor_gpu_read_64bit_counter(struct panthor_device *ptdev, u32 reg)
|
||||
{
|
||||
u32 hi, lo;
|
||||
|
||||
do {
|
||||
hi = gpu_read(ptdev, reg + 0x4);
|
||||
lo = gpu_read(ptdev, reg);
|
||||
} while (hi != gpu_read(ptdev, reg + 0x4));
|
||||
|
||||
return ((u64)hi << 32) | lo;
|
||||
}
|
||||
|
||||
/**
|
||||
* panthor_gpu_read_timestamp() - Read the timestamp register.
|
||||
* @ptdev: Device.
|
||||
*
|
||||
* Return: The GPU timestamp value.
|
||||
*/
|
||||
u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev)
|
||||
{
|
||||
return panthor_gpu_read_64bit_counter(ptdev, GPU_TIMESTAMP_LO);
|
||||
}
|
||||
|
||||
/**
|
||||
* panthor_gpu_read_timestamp_offset() - Read the timestamp offset register.
|
||||
* @ptdev: Device.
|
||||
*
|
||||
* Return: The GPU timestamp offset value.
|
||||
*/
|
||||
u64 panthor_gpu_read_timestamp_offset(struct panthor_device *ptdev)
|
||||
{
|
||||
u32 hi, lo;
|
||||
|
||||
hi = gpu_read(ptdev, GPU_TIMESTAMP_OFFSET_HI);
|
||||
lo = gpu_read(ptdev, GPU_TIMESTAMP_OFFSET_LO);
|
||||
|
||||
return ((u64)hi << 32) | lo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#ifndef __PANTHOR_GPU_H__
|
||||
#define __PANTHOR_GPU_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct panthor_device;
|
||||
|
||||
int panthor_gpu_init(struct panthor_device *ptdev);
|
||||
|
|
@ -48,5 +50,7 @@ int panthor_gpu_l2_power_on(struct panthor_device *ptdev);
|
|||
int panthor_gpu_flush_caches(struct panthor_device *ptdev,
|
||||
u32 l2, u32 lsc, u32 other);
|
||||
int panthor_gpu_soft_reset(struct panthor_device *ptdev);
|
||||
u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev);
|
||||
u64 panthor_gpu_read_timestamp_offset(struct panthor_device *ptdev);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -260,6 +260,9 @@ enum drm_panthor_dev_query_type {
|
|||
|
||||
/** @DRM_PANTHOR_DEV_QUERY_CSIF_INFO: Query command-stream interface information. */
|
||||
DRM_PANTHOR_DEV_QUERY_CSIF_INFO,
|
||||
|
||||
/** @DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO: Query timestamp information. */
|
||||
DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -377,6 +380,25 @@ struct drm_panthor_csif_info {
|
|||
__u32 pad;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_panthor_timestamp_info - Timestamp information
|
||||
*
|
||||
* Structure grouping all queryable information relating to the GPU timestamp.
|
||||
*/
|
||||
struct drm_panthor_timestamp_info {
|
||||
/**
|
||||
* @timestamp_frequency: The frequency of the timestamp timer or 0 if
|
||||
* unknown.
|
||||
*/
|
||||
__u64 timestamp_frequency;
|
||||
|
||||
/** @current_timestamp: The current timestamp. */
|
||||
__u64 current_timestamp;
|
||||
|
||||
/** @timestamp_offset: The offset of the timestamp timer. */
|
||||
__u64 timestamp_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_panthor_dev_query - Arguments passed to DRM_PANTHOR_IOCTL_DEV_QUERY
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue