diff --git a/drivers/gpu/nvgpu/common/ptimer/ptimer.c b/drivers/gpu/nvgpu/common/ptimer/ptimer.c index e53eb3cb9..2bfbfb519 100644 --- a/drivers/gpu/nvgpu/common/ptimer/ptimer.c +++ b/drivers/gpu/nvgpu/common/ptimer/ptimer.c @@ -26,6 +26,7 @@ #include #include #include +#include #endif static u32 ptimer_scalingfactor10x(u32 ptimer_src_freq) @@ -77,14 +78,13 @@ int nvgpu_ptimer_init(struct gk20a *g) } int nvgpu_get_timestamps_zipper(struct gk20a *g, - u32 source_id, u32 count, + enum nvgpu_cpu_timestamp_source cpu_timestamp_source, + u32 count, struct nvgpu_cpu_time_correlation_sample *samples) { int err = 0; unsigned int i = 0; - (void)source_id; - if (gk20a_busy(g) != 0) { nvgpu_err(g, "GPU not powered on\n"); err = -EINVAL; @@ -97,7 +97,12 @@ int nvgpu_get_timestamps_zipper(struct gk20a *g, goto idle; } - samples[i].cpu_timestamp = nvgpu_hr_timestamp(); + /* The cpu timestamp is already validated when handling ioctl/devctls */ + if (cpu_timestamp_source == NVGPU_CPU_TIMESTAMP_SOURCE_TSC) { + samples[i].cpu_timestamp = nvgpu_hr_timestamp(); + } else if (cpu_timestamp_source == NVGPU_CPU_TIMESTAMP_SOURCE_UNIX) { + samples[i].cpu_timestamp = nvgpu_current_unix_time_us(); + } } idle: diff --git a/drivers/gpu/nvgpu/include/nvgpu/ptimer.h b/drivers/gpu/nvgpu/include/nvgpu/ptimer.h index e0b87a656..1044e99fc 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/ptimer.h +++ b/drivers/gpu/nvgpu/include/nvgpu/ptimer.h @@ -144,8 +144,21 @@ struct nvgpu_cpu_time_correlation_sample { int nvgpu_ptimer_scale(struct gk20a *g, u32 timeout, u32 *scaled_timeout); #ifdef CONFIG_NVGPU_IOCTL_NON_FUSA + +/* + + */ +enum nvgpu_cpu_timestamp_source { + /* The timestamp is selected to originate from the current core's TSC */ + NVGPU_CPU_TIMESTAMP_SOURCE_TSC, + + /* The timestamp is selected to be calculated as UNIX time in microseconds */ + NVGPU_CPU_TIMESTAMP_SOURCE_UNIX, +}; + int nvgpu_get_timestamps_zipper(struct gk20a *g, - u32 source_id, u32 count, + enum nvgpu_cpu_timestamp_source cpu_timestamp_source, + u32 count, struct nvgpu_cpu_time_correlation_sample *samples); int nvgpu_ptimer_init(struct gk20a *g); #endif /* CONFIG_NVGPU_IOCTL_NON_FUSA */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/timers.h b/drivers/gpu/nvgpu/include/nvgpu/timers.h index d60da3847..816169db9 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/timers.h +++ b/drivers/gpu/nvgpu/include/nvgpu/timers.h @@ -363,6 +363,13 @@ u64 nvgpu_hr_timestamp_us(void); * @return High resolution time stamp value. */ u64 nvgpu_hr_timestamp(void); + +/** + * @brief UNIX timestamp. + * + * @return High resolution UNIX time stamp value. + */ +u64 nvgpu_current_unix_time_us(void); #endif /** diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 91ded2fdb..2951633d9 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c @@ -1230,13 +1230,24 @@ static int nvgpu_gpu_get_cpu_time_correlation_info( struct nvgpu_gpu_get_cpu_time_correlation_info_args *args) { struct nvgpu_cpu_time_correlation_sample *samples; + enum nvgpu_cpu_timestamp_source timestamp_source; int err; u32 i; - if (args->count > NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_MAX_COUNT || - args->source_id != NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_TSC) + 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: + timestamp_source = NVGPU_CPU_TIMESTAMP_SOURCE_TSC; + break; + case NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_OSTIME: + timestamp_source = NVGPU_CPU_TIMESTAMP_SOURCE_UNIX; + break; + default: + return -EINVAL; + } + samples = nvgpu_kzalloc(g, args->count * sizeof(struct nvgpu_cpu_time_correlation_sample)); if (!samples) { @@ -1244,7 +1255,7 @@ static int nvgpu_gpu_get_cpu_time_correlation_info( } err = g->ops.ptimer.get_timestamps_zipper(g, - args->source_id, args->count, samples); + timestamp_source, args->count, samples); if (!err) { for (i = 0; i < args->count; i++) { args->samples[i].cpu_timestamp = samples[i].cpu_timestamp; diff --git a/drivers/gpu/nvgpu/os/linux/timers.c b/drivers/gpu/nvgpu/os/linux/timers.c index ef2208fff..e7d92e366 100644 --- a/drivers/gpu/nvgpu/os/linux/timers.c +++ b/drivers/gpu/nvgpu/os/linux/timers.c @@ -271,6 +271,17 @@ s64 nvgpu_current_time_ns(void) return ktime_to_ns(ktime_get()); } +/** + * nvgpu_current_unix_time_us - UNIX time in microseconds from a monotonic clock. + * + * Returns the UNIX clock in microseconds units. The start time of the clock is + * 1970 00:00:00. + */ +u64 nvgpu_current_unix_time_us(void) +{ + return (u64)ktime_to_us(ktime_get_real()); +} + /** * nvgpu_hr_timestamp_us - Time in microseconds from a monotonic clock. * diff --git a/include/uapi/linux/nvgpu-ctrl.h b/include/uapi/linux/nvgpu-ctrl.h index 3f70029a9..b650eb078 100644 --- a/include/uapi/linux/nvgpu-ctrl.h +++ b/include/uapi/linux/nvgpu-ctrl.h @@ -684,6 +684,7 @@ struct nvgpu_gpu_get_buffer_info_args { #define NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_MAX_COUNT 16 #define NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_TSC 1 +#define NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_OSTIME 2 struct nvgpu_gpu_get_cpu_time_correlation_sample { /* gpu timestamp value */