summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
diff options
context:
space:
mode:
authorSami Kiminki <skiminki@nvidia.com>2016-04-12 15:33:36 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2016-04-15 17:05:23 -0400
commit6b35cb05b7822174bf037da7229154004df4f229 (patch)
tree7b0bf53f809160322c310a885759794c9c79161c /drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
parent701803d489ad1e2ba818a637f81f42aa6c484eb2 (diff)
gpu: nvgpu: Implement NVGPU_GPU_IOCTL_GET_GPU_TIME
Implement NVGPU_GPU_IOCTL_GET_GPU_TIME for reading the GPU time. Bug 1395833 Change-Id: I7ddc7c28ff0c9a336cc0dcd820b15fb0fea714d0 Signed-off-by: Sami Kiminki <skiminki@nvidia.com> Reviewed-on: http://git-master/r/1125630 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c57
1 files changed, 57 insertions, 0 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;