summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c97
1 files changed, 65 insertions, 32 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