From 032efd066ec4a8034204b6a34663ab2cac582fbe Mon Sep 17 00:00:00 2001 From: Arul Sekar Date: Fri, 11 Mar 2016 11:24:20 -0800 Subject: gpu: nvgpu: Provide cpu gpu time correlation via ioctl bug 1648908 Provides pairs of CPU and GPU timestamps that can be used for correlatiing the two timebases - IOCTL made available /dev/nvhost-ctrl-gpu Change-Id: I1458b9d33d794b1b02ec9fd29ed9426756b94bcd Signed-off-by: Arul Sekar Reviewed-on: http://git-master/r/1029732 Reviewed-by: Arun Gona Tested-by: Arun Gona Reviewed-on: http://git-master/r/1111715 GVS: Gerrit_Virtual_Submit Reviewed-by: Thomas Fleury Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | 94 ++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/hw_timer_gk20a.h | 10 +++- drivers/gpu/nvgpu/gm20b/hw_timer_gm20b.h | 10 +++- 3 files changed, 112 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c index 11790f4a..b2ae224f 100644 --- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c @@ -29,6 +29,7 @@ #include "hw_gr_gk20a.h" #include "hw_fb_gk20a.h" #include "hw_proj_gk20a.h" +#include "hw_timer_gk20a.h" int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp) { @@ -530,6 +531,94 @@ static int gk20a_ctrl_get_buffer_info( &args->out.id, &args->out.length); } +static inline u64 get_cpu_timestamp_tsc(void) +{ + return ((u64) get_cycles()); +} + +static inline u64 get_cpu_timestamp_jiffies(void) +{ + return (get_jiffies_64() - INITIAL_JIFFIES); +} + +static inline u64 get_cpu_timestamp_timeofday(void) +{ + struct timeval tv; + + do_gettimeofday(&tv); + return timeval_to_jiffies(&tv); +} + +static inline int get_timestamps_zipper(struct gk20a *g, + u64 (*get_cpu_timestamp)(void), + struct nvgpu_gpu_get_cpu_time_correlation_info_args *args) +{ + int err = 0; + int i = 0; + u32 gpu_timestamp_hi_new = 0; + u32 gpu_timestamp_hi_old = 0; + + if (gk20a_busy(g->dev)) { + gk20a_err(dev_from_gk20a(g), "GPU not powered on\n"); + err = -EINVAL; + goto end; + } + + /* get zipper reads of gpu and cpu counter values */ + gpu_timestamp_hi_old = gk20a_readl(g, timer_time_1_r()); + for (i = 0; i < args->count; i++) { + u32 gpu_timestamp_lo = 0; + u32 gpu_timestamp_hi = 0; + + gpu_timestamp_lo = gk20a_readl(g, timer_time_0_r()); + args->samples[i].cpu_timestamp = get_cpu_timestamp(); + rmb(); /* maintain zipper read order */ + gpu_timestamp_hi_new = gk20a_readl(g, timer_time_1_r()); + + /* pick the appropriate gpu counter hi bits */ + gpu_timestamp_hi = (gpu_timestamp_lo & (1L << 31)) ? + gpu_timestamp_hi_old : gpu_timestamp_hi_new; + + args->samples[i].gpu_timestamp = + ((u64)gpu_timestamp_hi << 32) | (u64)gpu_timestamp_lo; + + gpu_timestamp_hi_old = gpu_timestamp_hi_new; + } + +end: + gk20a_idle(g->dev); + return err; +} + +static int nvgpu_gpu_get_cpu_time_correlation_info( + struct gk20a *g, + struct nvgpu_gpu_get_cpu_time_correlation_info_args *args) +{ + int err = 0; + u64 (*get_cpu_timestamp)(void) = NULL; + + if (args->count > NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_MAX_COUNT) + return -EINVAL; + + switch (args->source_id) { + case NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_TSC: + get_cpu_timestamp = get_cpu_timestamp_tsc; + break; + case NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_JIFFIES: + get_cpu_timestamp = get_cpu_timestamp_jiffies; + break; + case NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_TIMEOFDAY: + get_cpu_timestamp = get_cpu_timestamp_timeofday; + break; + default: + gk20a_err(dev_from_gk20a(g), "invalid cpu clock source id\n"); + return -EINVAL; + } + + err = get_timestamps_zipper(g, get_cpu_timestamp, args); + return err; +} + long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct platform_device *dev = filp->private_data; @@ -762,6 +851,11 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg (struct nvgpu_gpu_get_buffer_info_args *)buf); break; + case NVGPU_GPU_IOCTL_GET_CPU_TIME_CORRELATION_INFO: + err = nvgpu_gpu_get_cpu_time_correlation_info(g, + (struct nvgpu_gpu_get_cpu_time_correlation_info_args *)buf); + break; + default: dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd); err = -ENOTTY; diff --git a/drivers/gpu/nvgpu/gk20a/hw_timer_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_timer_gk20a.h index 22bc50ac..dbbc914f 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_timer_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_timer_gk20a.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -98,4 +98,12 @@ static inline u32 timer_pri_timeout_fecs_errcode_r(void) { return 0x0000908c; } +static inline u32 timer_time_0_r(void) +{ + return 0x00009400; +} +static inline u32 timer_time_1_r(void) +{ + return 0x00009410; +} #endif diff --git a/drivers/gpu/nvgpu/gm20b/hw_timer_gm20b.h b/drivers/gpu/nvgpu/gm20b/hw_timer_gm20b.h index 126f7c8c..06d02522 100644 --- a/drivers/gpu/nvgpu/gm20b/hw_timer_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/hw_timer_gm20b.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -98,4 +98,12 @@ static inline u32 timer_pri_timeout_fecs_errcode_r(void) { return 0x0000908c; } +static inline u32 timer_time_0_r(void) +{ + return 0x00009400; +} +static inline u32 timer_time_1_r(void) +{ + return 0x00009410; +} #endif -- cgit v1.2.2