History

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

Mary Guillemard committed 2 years ago

Commit a7780281 parent c6430a84 files · +115 −1Browse files

Unified · Split

4 files
  1. drivers/gpu/drm/panthor/panthor_drv.c +42 −1
  2. drivers/gpu/drm/panthor/panthor_gpu.c +47 −0
  3. drivers/gpu/drm/panthor/panthor_gpu.h +4 −0
  4. include/uapi/drm/panthor_drm.h +22 −0
drivers/gpu/drm/panthor/panthor_drv.c+42−1
@@ -3,6 +3,10 @@ · 2 unmodified lines
3/* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */3/* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */
4/* Copyright 2019 Collabora ltd. */4/* Copyright 2019 Collabora ltd. */
5 5
6#ifdef CONFIG_ARM_ARCH_TIMER
7#include <asm/arch_timer.h>
8#endif
9
6#include <linux/list.h>10#include <linux/list.h>
7#include <linux/module.h>11#include <linux/module.h>
8#include <linux/of_platform.h>12#include <linux/of_platform.h>
@@ -164,6 +168,7 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride, · 155 unmodified lines
164 _Generic(_obj_name, \168 _Generic(_obj_name, \
165 PANTHOR_UOBJ_DECL(struct drm_panthor_gpu_info, tiler_present), \169 PANTHOR_UOBJ_DECL(struct drm_panthor_gpu_info, tiler_present), \
166 PANTHOR_UOBJ_DECL(struct drm_panthor_csif_info, pad), \170 PANTHOR_UOBJ_DECL(struct drm_panthor_csif_info, pad), \
171 PANTHOR_UOBJ_DECL(struct drm_panthor_timestamp_info, current_timestamp), \
167 PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \172 PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \
168 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \173 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \
169 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \174 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, · 580 unmodified lines
750 kvfree(ctx->jobs);755 kvfree(ctx->jobs);
751}756}
752 757
758static int panthor_query_timestamp_info(struct panthor_device *ptdev,
759 struct drm_panthor_timestamp_info *arg)
760{
761 int ret;
762
763 ret = pm_runtime_resume_and_get(ptdev->base.dev);
764 if (ret)
765 return ret;
766
767#ifdef CONFIG_ARM_ARCH_TIMER
768 arg->timestamp_frequency = arch_timer_get_cntfrq();
769#else
770 arg->timestamp_frequency = 0;
771#endif
772 arg->current_timestamp = panthor_gpu_read_timestamp(ptdev);
773 arg->timestamp_offset = panthor_gpu_read_timestamp_offset(ptdev);
774
775 pm_runtime_put(ptdev->base.dev);
776 return 0;
777}
778
753static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct drm_file *file)779static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct drm_file *file)
754{780{
755 struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);781 struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
756 struct drm_panthor_dev_query *args = data;782 struct drm_panthor_dev_query *args = data;
783 struct drm_panthor_timestamp_info timestamp_info;
784 int ret;
757 785
758 if (!args->pointer) {786 if (!args->pointer) {
759 switch (args->type) {787 switch (args->type) {
@@ -765,6 +793,10 @@ static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct d · 5 unmodified lines
765 args->size = sizeof(ptdev->csif_info);793 args->size = sizeof(ptdev->csif_info);
766 return 0;794 return 0;
767 795
796 case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO:
797 args->size = sizeof(timestamp_info);
798 return 0;
799
768 default:800 default:
769 return -EINVAL;801 return -EINVAL;
770 }802 }
@@ -777,6 +809,14 @@ static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct d · 6 unmodified lines
777 case DRM_PANTHOR_DEV_QUERY_CSIF_INFO:809 case DRM_PANTHOR_DEV_QUERY_CSIF_INFO:
778 return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info);810 return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info);
779 811
812 case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO:
813 ret = panthor_query_timestamp_info(ptdev, &timestamp_info);
814
815 if (ret)
816 return ret;
817
818 return PANTHOR_UOBJ_SET(args->pointer, args->size, timestamp_info);
819
780 default:820 default:
781 return -EINVAL;821 return -EINVAL;
782 }822 }
@@ -1372,6 +1412,7 @@ static void panthor_debugfs_init(struct drm_minor *minor) · 589 unmodified lines
1372/*1412/*
1373 * PanCSF driver version:1413 * PanCSF driver version:
1374 * - 1.0 - initial interface1414 * - 1.0 - initial interface
1415 * - 1.1 - adds DEV_QUERY_TIMESTAMP_INFO query
1375 */1416 */
1376static const struct drm_driver panthor_drm_driver = {1417static const struct drm_driver panthor_drm_driver = {
1377 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |1418 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
@@ -1385,7 +1426,7 @@ static const struct drm_driver panthor_drm_driver = { · 7 unmodified lines
1385 .desc = "Panthor DRM driver",1426 .desc = "Panthor DRM driver",
1386 .date = "20230801",1427 .date = "20230801",
1387 .major = 1,1428 .major = 1,
1388 .minor = 0,1429 .minor = 1,
1389 1430
1390 .gem_create_object = panthor_gem_create_object,1431 .gem_create_object = panthor_gem_create_object,
1391 .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,1432 .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
drivers/gpu/drm/panthor/panthor_gpu.c+47−0
@@ -480,3 +480,50 @@ void panthor_gpu_resume(struct panthor_device *ptdev) · 479 unmodified lines
480 panthor_gpu_irq_resume(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK);480 panthor_gpu_irq_resume(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK);
481 panthor_gpu_l2_power_on(ptdev);481 panthor_gpu_l2_power_on(ptdev);
482}482}
483
484/**
485 * panthor_gpu_read_64bit_counter() - Read a 64-bit counter at a given offset.
486 * @ptdev: Device.
487 * @reg: The offset of the register to read.
488 *
489 * Return: The counter value.
490 */
491static u64
492panthor_gpu_read_64bit_counter(struct panthor_device *ptdev, u32 reg)
493{
494 u32 hi, lo;
495
496 do {
497 hi = gpu_read(ptdev, reg + 0x4);
498 lo = gpu_read(ptdev, reg);
499 } while (hi != gpu_read(ptdev, reg + 0x4));
500
501 return ((u64)hi << 32) | lo;
502}
503
504/**
505 * panthor_gpu_read_timestamp() - Read the timestamp register.
506 * @ptdev: Device.
507 *
508 * Return: The GPU timestamp value.
509 */
510u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev)
511{
512 return panthor_gpu_read_64bit_counter(ptdev, GPU_TIMESTAMP_LO);
513}
514
515/**
516 * panthor_gpu_read_timestamp_offset() - Read the timestamp offset register.
517 * @ptdev: Device.
518 *
519 * Return: The GPU timestamp offset value.
520 */
521u64 panthor_gpu_read_timestamp_offset(struct panthor_device *ptdev)
522{
523 u32 hi, lo;
524
525 hi = gpu_read(ptdev, GPU_TIMESTAMP_OFFSET_HI);
526 lo = gpu_read(ptdev, GPU_TIMESTAMP_OFFSET_LO);
527
528 return ((u64)hi << 32) | lo;
529}
drivers/gpu/drm/panthor/panthor_gpu.h+4−0
@@ -5,6 +5,8 @@ · 4 unmodified lines
5#ifndef __PANTHOR_GPU_H__5#ifndef __PANTHOR_GPU_H__
6#define __PANTHOR_GPU_H__6#define __PANTHOR_GPU_H__
7 7
8#include <linux/types.h>
9
8struct panthor_device;10struct panthor_device;
9 11
10int panthor_gpu_init(struct panthor_device *ptdev);12int panthor_gpu_init(struct panthor_device *ptdev);
@@ -48,5 +50,7 @@ int panthor_gpu_l2_power_on(struct panthor_device *ptdev); · 37 unmodified lines
48int panthor_gpu_flush_caches(struct panthor_device *ptdev,50int panthor_gpu_flush_caches(struct panthor_device *ptdev,
49 u32 l2, u32 lsc, u32 other);51 u32 l2, u32 lsc, u32 other);
50int panthor_gpu_soft_reset(struct panthor_device *ptdev);52int panthor_gpu_soft_reset(struct panthor_device *ptdev);
53u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev);
54u64 panthor_gpu_read_timestamp_offset(struct panthor_device *ptdev);
51 55
52#endif56#endif
include/uapi/drm/panthor_drm.h+22−0
@@ -260,6 +260,9 @@ enum drm_panthor_dev_query_type { · 259 unmodified lines
260 260
261 /** @DRM_PANTHOR_DEV_QUERY_CSIF_INFO: Query command-stream interface information. */261 /** @DRM_PANTHOR_DEV_QUERY_CSIF_INFO: Query command-stream interface information. */
262 DRM_PANTHOR_DEV_QUERY_CSIF_INFO,262 DRM_PANTHOR_DEV_QUERY_CSIF_INFO,
263
264 /** @DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO: Query timestamp information. */
265 DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO,
263};266};
264 267
265/**268/**
@@ -377,6 +380,25 @@ struct drm_panthor_csif_info { · 111 unmodified lines
377 __u32 pad;380 __u32 pad;
378};381};
379 382
383/**
384 * struct drm_panthor_timestamp_info - Timestamp information
385 *
386 * Structure grouping all queryable information relating to the GPU timestamp.
387 */
388struct drm_panthor_timestamp_info {
389 /**
390 * @timestamp_frequency: The frequency of the timestamp timer or 0 if
391 * unknown.
392 */
393 __u64 timestamp_frequency;
394
395 /** @current_timestamp: The current timestamp. */
396 __u64 current_timestamp;
397
398 /** @timestamp_offset: The offset of the timestamp timer. */
399 __u64 timestamp_offset;
400};
401
380/**402/**
381 * struct drm_panthor_dev_query - Arguments passed to DRM_PANTHOR_IOCTL_DEV_QUERY403 * struct drm_panthor_dev_query - Arguments passed to DRM_PANTHOR_IOCTL_DEV_QUERY
382 */404 */