diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c index 9ed5fef3..b2ae224f 100644 --- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "hw_gr_gk20a.h" | 29 | #include "hw_gr_gk20a.h" |
30 | #include "hw_fb_gk20a.h" | 30 | #include "hw_fb_gk20a.h" |
31 | #include "hw_proj_gk20a.h" | 31 | #include "hw_proj_gk20a.h" |
32 | #include "hw_timer_gk20a.h" | ||
32 | 33 | ||
33 | int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp) | 34 | int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp) |
34 | { | 35 | { |
@@ -272,6 +273,8 @@ static int nvgpu_gpu_ioctl_inval_icache( | |||
272 | struct nvgpu_dbg_gpu_reg_op ops; | 273 | struct nvgpu_dbg_gpu_reg_op ops; |
273 | 274 | ||
274 | ch = gk20a_get_channel_from_file(args->channel_fd); | 275 | ch = gk20a_get_channel_from_file(args->channel_fd); |
276 | if (!ch) | ||
277 | return -EINVAL; | ||
275 | 278 | ||
276 | ops.op = REGOP(READ_32); | 279 | ops.op = REGOP(READ_32); |
277 | ops.type = REGOP(TYPE_GR_CTX); | 280 | ops.type = REGOP(TYPE_GR_CTX); |
@@ -528,6 +531,94 @@ static int gk20a_ctrl_get_buffer_info( | |||
528 | &args->out.id, &args->out.length); | 531 | &args->out.id, &args->out.length); |
529 | } | 532 | } |
530 | 533 | ||
534 | static inline u64 get_cpu_timestamp_tsc(void) | ||
535 | { | ||
536 | return ((u64) get_cycles()); | ||
537 | } | ||
538 | |||
539 | static inline u64 get_cpu_timestamp_jiffies(void) | ||
540 | { | ||
541 | return (get_jiffies_64() - INITIAL_JIFFIES); | ||
542 | } | ||
543 | |||
544 | static inline u64 get_cpu_timestamp_timeofday(void) | ||
545 | { | ||
546 | struct timeval tv; | ||
547 | |||
548 | do_gettimeofday(&tv); | ||
549 | return timeval_to_jiffies(&tv); | ||
550 | } | ||
551 | |||
552 | static inline int get_timestamps_zipper(struct gk20a *g, | ||
553 | u64 (*get_cpu_timestamp)(void), | ||
554 | struct nvgpu_gpu_get_cpu_time_correlation_info_args *args) | ||
555 | { | ||
556 | int err = 0; | ||
557 | int i = 0; | ||
558 | u32 gpu_timestamp_hi_new = 0; | ||
559 | u32 gpu_timestamp_hi_old = 0; | ||
560 | |||
561 | if (gk20a_busy(g->dev)) { | ||
562 | gk20a_err(dev_from_gk20a(g), "GPU not powered on\n"); | ||
563 | err = -EINVAL; | ||
564 | goto end; | ||
565 | } | ||
566 | |||
567 | /* get zipper reads of gpu and cpu counter values */ | ||
568 | gpu_timestamp_hi_old = gk20a_readl(g, timer_time_1_r()); | ||
569 | for (i = 0; i < args->count; i++) { | ||
570 | u32 gpu_timestamp_lo = 0; | ||
571 | u32 gpu_timestamp_hi = 0; | ||
572 | |||
573 | gpu_timestamp_lo = gk20a_readl(g, timer_time_0_r()); | ||
574 | args->samples[i].cpu_timestamp = get_cpu_timestamp(); | ||
575 | rmb(); /* maintain zipper read order */ | ||
576 | gpu_timestamp_hi_new = gk20a_readl(g, timer_time_1_r()); | ||
577 | |||
578 | /* pick the appropriate gpu counter hi bits */ | ||
579 | gpu_timestamp_hi = (gpu_timestamp_lo & (1L << 31)) ? | ||
580 | gpu_timestamp_hi_old : gpu_timestamp_hi_new; | ||
581 | |||
582 | args->samples[i].gpu_timestamp = | ||
583 | ((u64)gpu_timestamp_hi << 32) | (u64)gpu_timestamp_lo; | ||
584 | |||
585 | gpu_timestamp_hi_old = gpu_timestamp_hi_new; | ||
586 | } | ||
587 | |||
588 | end: | ||
589 | gk20a_idle(g->dev); | ||
590 | return err; | ||
591 | } | ||
592 | |||
593 | static int nvgpu_gpu_get_cpu_time_correlation_info( | ||
594 | struct gk20a *g, | ||
595 | struct nvgpu_gpu_get_cpu_time_correlation_info_args *args) | ||
596 | { | ||
597 | int err = 0; | ||
598 | u64 (*get_cpu_timestamp)(void) = NULL; | ||
599 | |||
600 | if (args->count > NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_MAX_COUNT) | ||
601 | return -EINVAL; | ||
602 | |||
603 | switch (args->source_id) { | ||
604 | case NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_TSC: | ||
605 | get_cpu_timestamp = get_cpu_timestamp_tsc; | ||
606 | break; | ||
607 | case NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_JIFFIES: | ||
608 | get_cpu_timestamp = get_cpu_timestamp_jiffies; | ||
609 | break; | ||
610 | case NVGPU_GPU_GET_CPU_TIME_CORRELATION_INFO_SRC_ID_TIMEOFDAY: | ||
611 | get_cpu_timestamp = get_cpu_timestamp_timeofday; | ||
612 | break; | ||
613 | default: | ||
614 | gk20a_err(dev_from_gk20a(g), "invalid cpu clock source id\n"); | ||
615 | return -EINVAL; | ||
616 | } | ||
617 | |||
618 | err = get_timestamps_zipper(g, get_cpu_timestamp, args); | ||
619 | return err; | ||
620 | } | ||
621 | |||
531 | long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 622 | long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
532 | { | 623 | { |
533 | struct platform_device *dev = filp->private_data; | 624 | struct platform_device *dev = filp->private_data; |
@@ -760,6 +851,11 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg | |||
760 | (struct nvgpu_gpu_get_buffer_info_args *)buf); | 851 | (struct nvgpu_gpu_get_buffer_info_args *)buf); |
761 | break; | 852 | break; |
762 | 853 | ||
854 | case NVGPU_GPU_IOCTL_GET_CPU_TIME_CORRELATION_INFO: | ||
855 | err = nvgpu_gpu_get_cpu_time_correlation_info(g, | ||
856 | (struct nvgpu_gpu_get_cpu_time_correlation_info_args *)buf); | ||
857 | break; | ||
858 | |||
763 | default: | 859 | default: |
764 | dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd); | 860 | dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd); |
765 | err = -ENOTTY; | 861 | err = -ENOTTY; |