diff options
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | 97 | ||||
-rw-r--r-- | include/uapi/linux/nvgpu.h | 35 |
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 | |||
527 | struct nvgpu_gpu_clk_range_args { | 530 | struct 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 | ||
607 | struct nvgpu_gpu_clk_get_info_args { | 611 | struct 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 | */ |