diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | 97 |
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 | ||