summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c97
-rw-r--r--include/uapi/linux/nvgpu.h35
2 files changed, 87 insertions, 45 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
index 7d344e9a..8e243eab 100644
--- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
@@ -917,37 +917,51 @@ static int nvgpu_gpu_clk_get_range(struct gk20a *g,
917 917
918 u32 clk_domains = 0; 918 u32 clk_domains = 0;
919 u32 num_domains; 919 u32 num_domains;
920 u32 i;
920 int bit; 921 int bit;
921 u16 min_mhz, max_mhz; 922 u16 min_mhz, max_mhz;
922 int err; 923 int err;
923 924
924 gk20a_dbg_fn(""); 925 gk20a_dbg_fn("");
925 926
926 if (!session || args->flags) 927 if (!session)
927 return -EINVAL; 928 return -EINVAL;
928 929
929 args->num_entries = 0; 930 if (!args->flags) {
931 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
932 num_domains = hweight_long(clk_domains);
930 933
931 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g); 934 if (!args->num_entries) {
932 num_domains = hweight_long(clk_domains); 935 args->num_entries = num_domains;
936 return 0;
937 }
933 938
934 if (!args->max_entries) { 939 if (args->num_entries < num_domains)
935 args->max_entries = num_domains; 940 return -EINVAL;
936 return 0;
937 }
938 941
939 if (args->max_entries < num_domains) 942 args->num_entries = 0;
940 return -EINVAL; 943
944 } else {
945 if (args->flags != NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS)
946 return -EINVAL;
947
948 num_domains = args->num_entries;
949 }
941 950
942 entry = (struct nvgpu_gpu_clk_range __user *) 951 entry = (struct nvgpu_gpu_clk_range __user *)
943 (uintptr_t)args->clk_range_entries; 952 (uintptr_t)args->clk_range_entries;
944 953
945 memset(&clk_range, 0, sizeof(clk_range)); 954 for (i = 0; i < num_domains; i++, entry++) {
946 955
947 while (clk_domains) { 956 if (args->flags == NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS) {
948 bit = ffs(clk_domains) - 1; 957 if (copy_from_user(&clk_range, (void __user *)entry,
949 958 sizeof(clk_range)))
950 clk_range.clk_domain = BIT(bit); 959 return -EFAULT;
960 } else {
961 bit = ffs(clk_domains) - 1;
962 clk_range.clk_domain = BIT(bit);
963 clk_domains &= ~BIT(bit);
964 }
951 965
952 err = nvgpu_clk_arb_get_arbiter_clk_range(g, 966 err = nvgpu_clk_arb_get_arbiter_clk_range(g,
953 clk_range.clk_domain, &min_mhz, &max_mhz); 967 clk_range.clk_domain, &min_mhz, &max_mhz);
@@ -956,13 +970,11 @@ static int nvgpu_gpu_clk_get_range(struct gk20a *g,
956 970
957 clk_range.min_mhz = min_mhz; 971 clk_range.min_mhz = min_mhz;
958 clk_range.max_mhz = max_mhz; 972 clk_range.max_mhz = max_mhz;
973 clk_range.flags = 0;
959 974
960 err = copy_to_user(entry, &clk_range, sizeof(clk_range)); 975 err = copy_to_user(entry, &clk_range, sizeof(clk_range));
961 if (err) 976 if (err)
962 return -EFAULT; 977 return -EFAULT;
963
964 entry++;
965 clk_domains &= ~BIT(bit);
966 } 978 }
967 979
968 args->num_entries = num_domains; 980 args->num_entries = num_domains;
@@ -1043,34 +1055,52 @@ static int nvgpu_gpu_clk_get_info(struct gk20a *g,
1043 u32 num_domains; 1055 u32 num_domains;
1044 u16 actual_mhz; 1056 u16 actual_mhz;
1045 u16 target_mhz; 1057 u16 target_mhz;
1046 int err;
1047 u32 i; 1058 u32 i;
1059 int err;
1060 int bit;
1048 1061
1049 gk20a_dbg_fn(""); 1062 gk20a_dbg_fn("");
1050 1063
1051 if (!session || args->flags) 1064 if (!session)
1052 return -EINVAL;
1053
1054 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
1055 if (!clk_domains)
1056 return -EINVAL; 1065 return -EINVAL;
1057 1066
1058 args->last_req_nr = nvgpu_clk_arb_get_arbiter_req_nr(g); 1067 args->last_req_nr = nvgpu_clk_arb_get_arbiter_req_nr(g);
1059 1068
1060 num_domains = hweight_long(clk_domains); 1069 if (!args->flags) {
1061 if (!args->num_entries) { 1070 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
1062 args->num_entries = num_domains; 1071 num_domains = hweight_long(clk_domains);
1063 return 0; 1072
1073 if (!args->num_entries) {
1074 args->num_entries = num_domains;
1075 return 0;
1076 }
1077
1078 if (args->num_entries < num_domains)
1079 return -EINVAL;
1080
1081 args->num_entries = 0;
1082
1083 } else {
1084 if (args->flags != NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS)
1085 return -EINVAL;
1086
1087 num_domains = args->num_entries;
1064 } 1088 }
1065 1089
1066 entry = (struct nvgpu_gpu_clk_info __user *) 1090 entry = (struct nvgpu_gpu_clk_info __user *)
1067 (uintptr_t)args->clk_info_entries; 1091 (uintptr_t)args->clk_info_entries;
1068 1092
1069 for (i = 0; i < args->num_entries; i++, entry++) { 1093 for (i = 0; i < num_domains; i++, entry++) {
1070 1094
1071 if (copy_from_user(&clk_info, (void __user *)entry, 1095 if (args->flags == NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS) {
1072 sizeof(clk_info))) 1096 if (copy_from_user(&clk_info, (void __user *)entry,
1073 return -EFAULT; 1097 sizeof(clk_info)))
1098 return -EFAULT;
1099 } else {
1100 bit = ffs(clk_domains) - 1;
1101 clk_info.clk_domain = BIT(bit);
1102 clk_domains &= ~BIT(bit);
1103 }
1074 1104
1075 err = nvgpu_clk_arb_get_arbiter_actual_mhz(g, 1105 err = nvgpu_clk_arb_get_arbiter_actual_mhz(g,
1076 clk_info.clk_domain, &actual_mhz); 1106 clk_info.clk_domain, &actual_mhz);
@@ -1084,6 +1114,7 @@ static int nvgpu_gpu_clk_get_info(struct gk20a *g,
1084 1114
1085 clk_info.actual_mhz = actual_mhz; 1115 clk_info.actual_mhz = actual_mhz;
1086 clk_info.target_mhz = target_mhz; 1116 clk_info.target_mhz = target_mhz;
1117 clk_info.flags = 0;
1087 1118
1088 err = copy_to_user((void __user *)entry, &clk_info, 1119 err = copy_to_user((void __user *)entry, &clk_info,
1089 sizeof(clk_info)); 1120 sizeof(clk_info));
@@ -1091,6 +1122,8 @@ static int nvgpu_gpu_clk_get_info(struct gk20a *g,
1091 return -EFAULT; 1122 return -EFAULT;
1092 } 1123 }
1093 1124
1125 args->num_entries = num_domains;
1126
1094 return 0; 1127 return 0;
1095} 1128}
1096 1129
diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h
index d4582036..2d044db4 100644
--- a/include/uapi/linux/nvgpu.h
+++ b/include/uapi/linux/nvgpu.h
@@ -524,20 +524,24 @@ struct nvgpu_gpu_clk_range {
524 __u32 max_mhz; 524 __u32 max_mhz;
525}; 525};
526 526
527/* Request on specific clock domains */
528#define NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS (1UL << 0)
529
527struct nvgpu_gpu_clk_range_args { 530struct nvgpu_gpu_clk_range_args {
528 531
529 /* Flags (not currently used) */ 532 /* Flags. If NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS the request will
533 apply only to domains specified in clock entries. In this case
534 caller must set clock domain in each entry. Otherwise, the
535 ioctl will return all clock domains.
536 */
530 __u32 flags; 537 __u32 flags;
531 538
532 /* in/out: max number of entries in clk_range_entries buffer. If zero, 539 __u16 pad0;
533 NVGPU_GPU_IOCTL_CLK_GET_RANGE will return 0 and max_entries will be
534 set to the max number of clock domains. If there are more entries
535 than max_entries, then ioctl will return -EINVAL.
536 */
537 __u16 max_entries;
538 540
539 /* out: number of nvgpu_gpu_clk_range entries contained in 541 /* in/out: Number of entries in clk_range_entries buffer. If zero,
540 clk_range_entries */ 542 NVGPU_GPU_IOCTL_CLK_GET_RANGE will return 0 and
543 num_entries will be set to number of clock domains.
544 */
541 __u16 num_entries; 545 __u16 num_entries;
542 546
543 /* in: Pointer to clock range entries in the caller's address space. 547 /* in: Pointer to clock range entries in the caller's address space.
@@ -606,14 +610,18 @@ struct nvgpu_gpu_clk_info {
606 610
607struct nvgpu_gpu_clk_get_info_args { 611struct nvgpu_gpu_clk_get_info_args {
608 612
609 /* in: Flags (not currently used). */ 613 /* Flags. If NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS the request will
614 apply only to domains specified in clock entries. In this case
615 caller must set clock domain in each entry. Otherwise, the
616 ioctl will return all clock domains.
617 */
610 __u32 flags; 618 __u32 flags;
611 619
612 __u16 pad0; 620 __u16 pad0;
613 621
614 /* in/out: Number of clock info entries contained in clk_info_entries. 622 /* in/out: Number of clock info entries contained in clk_info_entries.
615 If zero, NVGPU_GPU_IOCTL_CLK_GET_INFO will return 0 and 623 If zero, NVGPU_GPU_IOCTL_CLK_GET_INFO will return 0 and
616 max_entries will be set to number of clock domains. Also, 624 num_entries will be set to number of clock domains. Also,
617 last_req_nr will be updated, which allows checking if a given 625 last_req_nr will be updated, which allows checking if a given
618 request has completed. If there are more entries than max_entries, 626 request has completed. If there are more entries than max_entries,
619 then ioctl will return -EINVAL. 627 then ioctl will return -EINVAL.
@@ -623,8 +631,9 @@ struct nvgpu_gpu_clk_get_info_args {
623 /* in: Pointer to nvgpu_gpu_clk_info entries in the caller's address 631 /* in: Pointer to nvgpu_gpu_clk_info entries in the caller's address
624 space. Buffer size must be at least: 632 space. Buffer size must be at least:
625 num_entries * sizeof(struct nvgpu_gpu_clk_info) 633 num_entries * sizeof(struct nvgpu_gpu_clk_info)
626 For each entry, the clk_domain to be queried should be set. Note 634 If NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS is set, caller should set
627 that clk_info_entries passed to an NVGPU_GPU_IOCTL_CLK_SET_INFO, 635 clk_domain to be queried in each entry. With this flag,
636 clk_info_entries passed to an NVGPU_GPU_IOCTL_CLK_SET_INFO,
628 can be re-used on completion for a NVGPU_GPU_IOCTL_CLK_GET_INFO. 637 can be re-used on completion for a NVGPU_GPU_IOCTL_CLK_GET_INFO.
629 This allows checking actual_mhz. 638 This allows checking actual_mhz.
630 */ 639 */