summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c57
-rw-r--r--include/uapi/linux/nvgpu.h13
2 files changed, 69 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
index b1d35141..56b4d947 100644
--- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
@@ -622,6 +622,58 @@ static int nvgpu_gpu_get_cpu_time_correlation_info(
622 return err; 622 return err;
623} 623}
624 624
625static int nvgpu_gpu_get_gpu_time(
626 struct gk20a *g,
627 struct nvgpu_gpu_get_gpu_time_args *args)
628{
629 int err = 0;
630 const unsigned int max_iterations = 3;
631 unsigned int i = 0;
632 u32 gpu_timestamp_hi_prev = 0;
633
634 err = gk20a_busy(g->dev);
635 if (err)
636 return err;
637
638 /* Note. The GPU nanosecond timer consists of two 32-bit
639 * registers (high & low). To detect a possible low register
640 * wrap-around between the reads, we need to read the high
641 * register before and after low. The wraparound happens
642 * approximately once per 4 secs. */
643
644 /* get initial gpu_timestamp_hi value */
645 gpu_timestamp_hi_prev = gk20a_readl(g, timer_time_1_r());
646
647 for (i = 0; i < max_iterations; ++i) {
648 u32 gpu_timestamp_hi = 0;
649 u32 gpu_timestamp_lo = 0;
650
651 rmb(); /* maintain read order */
652 gpu_timestamp_lo = gk20a_readl(g, timer_time_0_r());
653 rmb(); /* maintain read order */
654 gpu_timestamp_hi = gk20a_readl(g, timer_time_1_r());
655
656 if (gpu_timestamp_hi == gpu_timestamp_hi_prev) {
657 args->gpu_timestamp =
658 (((u64)gpu_timestamp_hi) << 32) |
659 gpu_timestamp_lo;
660 goto clean_up;
661 }
662
663 /* wrap-around detected, retry */
664 gpu_timestamp_hi_prev = gpu_timestamp_hi;
665 }
666
667 /* too many iterations, bail out */
668 gk20a_err(dev_from_gk20a(g),
669 "Failed to read GPU time. Clock or bus unstable?\n");
670 err = -EBUSY;
671
672clean_up:
673 gk20a_idle(g->dev);
674 return err;
675}
676
625long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 677long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
626{ 678{
627 struct device *dev = filp->private_data; 679 struct device *dev = filp->private_data;
@@ -859,6 +911,11 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg
859 (struct nvgpu_gpu_get_cpu_time_correlation_info_args *)buf); 911 (struct nvgpu_gpu_get_cpu_time_correlation_info_args *)buf);
860 break; 912 break;
861 913
914 case NVGPU_GPU_IOCTL_GET_GPU_TIME:
915 err = nvgpu_gpu_get_gpu_time(g,
916 (struct nvgpu_gpu_get_gpu_time_args *)buf);
917 break;
918
862 default: 919 default:
863 dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd); 920 dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd);
864 err = -ENOTTY; 921 err = -ENOTTY;
diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h
index d84c5440..cf89b9d8 100644
--- a/include/uapi/linux/nvgpu.h
+++ b/include/uapi/linux/nvgpu.h
@@ -377,6 +377,14 @@ struct nvgpu_gpu_get_cpu_time_correlation_info_args {
377 __u32 source_id; 377 __u32 source_id;
378}; 378};
379 379
380struct nvgpu_gpu_get_gpu_time_args {
381 /* raw GPU counter (PTIMER) value */
382 __u64 gpu_timestamp;
383
384 /* reserved for future extensions */
385 __u64 reserved;
386};
387
380#define NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE \ 388#define NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE \
381 _IOR(NVGPU_GPU_IOCTL_MAGIC, 1, struct nvgpu_gpu_zcull_get_ctx_size_args) 389 _IOR(NVGPU_GPU_IOCTL_MAGIC, 1, struct nvgpu_gpu_zcull_get_ctx_size_args)
382#define NVGPU_GPU_IOCTL_ZCULL_GET_INFO \ 390#define NVGPU_GPU_IOCTL_ZCULL_GET_INFO \
@@ -426,8 +434,11 @@ struct nvgpu_gpu_get_cpu_time_correlation_info_args {
426#define NVGPU_GPU_IOCTL_GET_CPU_TIME_CORRELATION_INFO \ 434#define NVGPU_GPU_IOCTL_GET_CPU_TIME_CORRELATION_INFO \
427 _IOWR(NVGPU_GPU_IOCTL_MAGIC, 24, \ 435 _IOWR(NVGPU_GPU_IOCTL_MAGIC, 24, \
428 struct nvgpu_gpu_get_cpu_time_correlation_info_args) 436 struct nvgpu_gpu_get_cpu_time_correlation_info_args)
437#define NVGPU_GPU_IOCTL_GET_GPU_TIME \
438 _IOWR(NVGPU_GPU_IOCTL_MAGIC, 25, \
439 struct nvgpu_gpu_get_gpu_time_args)
429#define NVGPU_GPU_IOCTL_LAST \ 440#define NVGPU_GPU_IOCTL_LAST \
430 _IOC_NR(NVGPU_GPU_IOCTL_GET_CPU_TIME_CORRELATION_INFO) 441 _IOC_NR(NVGPU_GPU_IOCTL_GET_GPU_TIME)
431#define NVGPU_GPU_IOCTL_MAX_ARG_SIZE \ 442#define NVGPU_GPU_IOCTL_MAX_ARG_SIZE \
432 sizeof(struct nvgpu_gpu_get_cpu_time_correlation_info_args) 443 sizeof(struct nvgpu_gpu_get_cpu_time_correlation_info_args)
433 444