summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Fleury <tfleury@nvidia.com>2016-09-13 17:25:28 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2016-12-07 18:01:14 -0500
commit05805ec65b2cd6413c9d0d711d3798fd457fed6e (patch)
tree8aacb5c36a72f86a183c0f210a2aeeac0c382ae3 /drivers
parent21094783114b9314d57f412196544a34b3a40f4a (diff)
gpu: nvgpu: ioctls for clock controls
Add ioctls for clock range and VF points query. Add ioctls to set target mhz, and get actual mhz. Jira DNVGPU-125 Change-Id: I7639789bb15eabd8c98adc468201dba3a6e19ade Signed-off-by: Thomas Fleury <tfleury@nvidia.com> Reviewed-on: http://git-master/r/1223473 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> (cherry picked from commit 5e635ae34221c99a739321bcfc1418db56c1051d) Reviewed-on: http://git-master/r/1243107 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c332
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c8
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h10
3 files changed, 347 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
index 56bc2c7a..7d344e9a 100644
--- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c
@@ -19,6 +19,7 @@
19#include <linux/file.h> 19#include <linux/file.h>
20#include <linux/anon_inodes.h> 20#include <linux/anon_inodes.h>
21#include <linux/nvgpu.h> 21#include <linux/nvgpu.h>
22#include <linux/bitops.h>
22#include <uapi/linux/nvgpu.h> 23#include <uapi/linux/nvgpu.h>
23#include <linux/delay.h> 24#include <linux/delay.h>
24 25
@@ -29,25 +30,55 @@
29#include "hw_gr_gk20a.h" 30#include "hw_gr_gk20a.h"
30#include "hw_fb_gk20a.h" 31#include "hw_fb_gk20a.h"
31#include "hw_timer_gk20a.h" 32#include "hw_timer_gk20a.h"
33#include "clk/clk_arb.h"
34
35
36struct gk20a_ctrl_priv {
37 struct device *dev;
38 struct nvgpu_clk_session *clk_session;
39};
32 40
33int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp) 41int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp)
34{ 42{
35 struct gk20a *g; 43 struct gk20a *g;
44 struct gk20a_ctrl_priv *priv;
45 int err;
36 46
37 gk20a_dbg_fn(""); 47 gk20a_dbg_fn("");
38 48
39 g = container_of(inode->i_cdev, 49 g = container_of(inode->i_cdev,
40 struct gk20a, ctrl.cdev); 50 struct gk20a, ctrl.cdev);
41 51
42 filp->private_data = g->dev; 52 priv = kzalloc(sizeof(struct gk20a_ctrl_priv), GFP_KERNEL);
53 if (!priv)
54 return -ENOMEM;
43 55
44 return 0; 56 filp->private_data = priv;
57 priv->dev = g->dev;
58
59 if (!g->gr.sw_ready) {
60 err = gk20a_busy(g->dev);
61 if (err)
62 return err;
63
64 gk20a_idle(g->dev);
65 }
66
67 return nvgpu_clk_arb_init_session(g, &priv->clk_session);
45} 68}
46 69
47int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp) 70int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp)
48{ 71{
72 struct gk20a_ctrl_priv *priv = filp->private_data;
73 struct gk20a *g = gk20a_from_dev(priv->dev);
74 struct nvgpu_clk_session *clk_session = priv->clk_session;
75
49 gk20a_dbg_fn(""); 76 gk20a_dbg_fn("");
50 77
78 if (clk_session)
79 nvgpu_clk_arb_cleanup_session(g, clk_session);
80 kfree(priv);
81
51 return 0; 82 return 0;
52} 83}
53 84
@@ -789,9 +820,284 @@ static int nvgpu_gpu_get_memory_state(struct gk20a *g,
789 return err; 820 return err;
790} 821}
791 822
823static int nvgpu_gpu_clk_get_vf_points(struct gk20a *g,
824 struct gk20a_ctrl_priv *priv,
825 struct nvgpu_gpu_clk_vf_points_args *args)
826{
827 struct nvgpu_gpu_clk_vf_point clk_point;
828 struct nvgpu_gpu_clk_vf_point __user *entry;
829 struct nvgpu_clk_session *session = priv->clk_session;
830 u32 clk_domains = 0;
831 int err;
832 u16 last_mhz;
833 u16 *fpoints;
834 u32 i;
835 u32 max_points = 0;
836 u32 num_points = 0;
837 u16 min_mhz;
838 u16 max_mhz;
839
840 gk20a_dbg_fn("");
841
842 if (!session || args->flags)
843 return -EINVAL;
844
845 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
846 args->num_entries = 0;
847
848 if ((args->clk_domain & clk_domains) == 0)
849 return -EINVAL;
850
851 err = nvgpu_clk_arb_get_arbiter_clk_f_points(g,
852 args->clk_domain, &max_points, NULL);
853 if (err)
854 return err;
855
856 if (!args->max_entries) {
857 args->max_entries = max_points;
858 return 0;
859 }
860
861 if (args->max_entries < max_points)
862 return -EINVAL;
863
864 err = nvgpu_clk_arb_get_arbiter_clk_range(g, args->clk_domain,
865 &min_mhz, &max_mhz);
866 if (err)
867 return err;
868
869 fpoints = kcalloc(max_points, sizeof(u16), GFP_KERNEL);
870 if (!fpoints)
871 return -ENOMEM;
872
873 err = nvgpu_clk_arb_get_arbiter_clk_f_points(g,
874 args->clk_domain, &max_points, fpoints);
875 if (err)
876 goto fail;
877
878 entry = (struct nvgpu_gpu_clk_vf_point __user *)
879 (uintptr_t)args->clk_vf_point_entries;
880
881 last_mhz = 0;
882 num_points = 0;
883 for (i = 0; (i < max_points) && !err; i++) {
884
885 /* filter out duplicate frequencies */
886 if (fpoints[i] == last_mhz)
887 continue;
888
889 /* filter out out-of-range frequencies */
890 if ((fpoints[i] < min_mhz) || (fpoints[i] > max_mhz))
891 continue;
892
893 last_mhz = fpoints[i];
894 clk_point.freq_mhz = fpoints[i];
895
896 err = copy_to_user((void __user *)entry, &clk_point,
897 sizeof(clk_point));
898
899 num_points++;
900 entry++;
901 }
902
903 args->num_entries = num_points;
904
905fail:
906 kfree(fpoints);
907 return err;
908}
909
910static int nvgpu_gpu_clk_get_range(struct gk20a *g,
911 struct gk20a_ctrl_priv *priv,
912 struct nvgpu_gpu_clk_range_args *args)
913{
914 struct nvgpu_gpu_clk_range clk_range;
915 struct nvgpu_gpu_clk_range __user *entry;
916 struct nvgpu_clk_session *session = priv->clk_session;
917
918 u32 clk_domains = 0;
919 u32 num_domains;
920 int bit;
921 u16 min_mhz, max_mhz;
922 int err;
923
924 gk20a_dbg_fn("");
925
926 if (!session || args->flags)
927 return -EINVAL;
928
929 args->num_entries = 0;
930
931 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
932 num_domains = hweight_long(clk_domains);
933
934 if (!args->max_entries) {
935 args->max_entries = num_domains;
936 return 0;
937 }
938
939 if (args->max_entries < num_domains)
940 return -EINVAL;
941
942 entry = (struct nvgpu_gpu_clk_range __user *)
943 (uintptr_t)args->clk_range_entries;
944
945 memset(&clk_range, 0, sizeof(clk_range));
946
947 while (clk_domains) {
948 bit = ffs(clk_domains) - 1;
949
950 clk_range.clk_domain = BIT(bit);
951
952 err = nvgpu_clk_arb_get_arbiter_clk_range(g,
953 clk_range.clk_domain, &min_mhz, &max_mhz);
954 if (err)
955 return err;
956
957 clk_range.min_mhz = min_mhz;
958 clk_range.max_mhz = max_mhz;
959
960 err = copy_to_user(entry, &clk_range, sizeof(clk_range));
961 if (err)
962 return -EFAULT;
963
964 entry++;
965 clk_domains &= ~BIT(bit);
966 }
967
968 args->num_entries = num_domains;
969
970 return 0;
971}
972
973
974static int nvgpu_gpu_clk_set_info(struct gk20a *g,
975 struct gk20a_ctrl_priv *priv,
976 struct nvgpu_gpu_clk_set_info_args *args)
977{
978 struct nvgpu_gpu_clk_info clk_info;
979 struct nvgpu_gpu_clk_info __user *entry;
980 struct nvgpu_clk_session *session = priv->clk_session;
981 u32 clk_domains = 0;
982 u32 i;
983 int fd;
984
985 gk20a_dbg_fn("");
986
987 if (!session || args->flags)
988 return -EINVAL;
989
990 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
991 if (!clk_domains)
992 return -EINVAL;
993
994 fd = nvgpu_clk_arb_install_session_fd(g, session);
995 if (fd < 0)
996 return fd;
997
998 entry = (struct nvgpu_gpu_clk_info __user *)
999 (uintptr_t)args->clk_info_entries;
1000
1001 for (i = 0; i < args->num_entries; i++, entry++) {
1002
1003 if (copy_from_user(&clk_info, entry, sizeof(clk_info)))
1004 return -EFAULT;
1005
1006 if ((clk_info.clk_domain & clk_domains) != clk_info.clk_domain)
1007 return -EINVAL;
1008
1009 if (hweight_long(clk_info.clk_domain) != 1)
1010 return -EINVAL;
1011 }
1012
1013 entry = (struct nvgpu_gpu_clk_info __user *)
1014 (uintptr_t)args->clk_info_entries;
1015
1016 for (i = 0; i < args->num_entries; i++, entry++) {
1017
1018 if (copy_from_user(&clk_info, (void __user *)entry,
1019 sizeof(clk_info)))
1020 return -EFAULT;
1021
1022 nvgpu_clk_arb_set_session_target_mhz(session,
1023 clk_info.clk_domain, clk_info.target_mhz);
1024 }
1025
1026 nvgpu_clk_arb_apply_session_constraints(g, session);
1027
1028 args->req_nr = nvgpu_clk_arb_get_session_req_nr(g, session);
1029 args->fd = fd;
1030
1031 return 0;
1032}
1033
1034
1035static int nvgpu_gpu_clk_get_info(struct gk20a *g,
1036 struct gk20a_ctrl_priv *priv,
1037 struct nvgpu_gpu_clk_get_info_args *args)
1038{
1039 struct nvgpu_gpu_clk_info clk_info;
1040 struct nvgpu_gpu_clk_info __user *entry;
1041 struct nvgpu_clk_session *session = priv->clk_session;
1042 u32 clk_domains = 0;
1043 u32 num_domains;
1044 u16 actual_mhz;
1045 u16 target_mhz;
1046 int err;
1047 u32 i;
1048
1049 gk20a_dbg_fn("");
1050
1051 if (!session || args->flags)
1052 return -EINVAL;
1053
1054 clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
1055 if (!clk_domains)
1056 return -EINVAL;
1057
1058 args->last_req_nr = nvgpu_clk_arb_get_arbiter_req_nr(g);
1059
1060 num_domains = hweight_long(clk_domains);
1061 if (!args->num_entries) {
1062 args->num_entries = num_domains;
1063 return 0;
1064 }
1065
1066 entry = (struct nvgpu_gpu_clk_info __user *)
1067 (uintptr_t)args->clk_info_entries;
1068
1069 for (i = 0; i < args->num_entries; i++, entry++) {
1070
1071 if (copy_from_user(&clk_info, (void __user *)entry,
1072 sizeof(clk_info)))
1073 return -EFAULT;
1074
1075 err = nvgpu_clk_arb_get_arbiter_actual_mhz(g,
1076 clk_info.clk_domain, &actual_mhz);
1077 if (err)
1078 return err;
1079
1080 err = nvgpu_clk_arb_get_session_target_mhz(session,
1081 clk_info.clk_domain, &target_mhz);
1082 if (err)
1083 return err;
1084
1085 clk_info.actual_mhz = actual_mhz;
1086 clk_info.target_mhz = target_mhz;
1087
1088 err = copy_to_user((void __user *)entry, &clk_info,
1089 sizeof(clk_info));
1090 if (err)
1091 return -EFAULT;
1092 }
1093
1094 return 0;
1095}
1096
792long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 1097long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
793{ 1098{
794 struct device *dev = filp->private_data; 1099 struct gk20a_ctrl_priv *priv = filp->private_data;
1100 struct device *dev = priv->dev;
795 struct gk20a *g = get_gk20a(dev); 1101 struct gk20a *g = get_gk20a(dev);
796 struct nvgpu_gpu_zcull_get_ctx_size_args *get_ctx_size_args; 1102 struct nvgpu_gpu_zcull_get_ctx_size_args *get_ctx_size_args;
797 struct nvgpu_gpu_zcull_get_info_args *get_info_args; 1103 struct nvgpu_gpu_zcull_get_info_args *get_info_args;
@@ -1050,6 +1356,26 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg
1050 (struct nvgpu_gpu_get_memory_state_args *)buf); 1356 (struct nvgpu_gpu_get_memory_state_args *)buf);
1051 break; 1357 break;
1052 1358
1359 case NVGPU_GPU_IOCTL_CLK_GET_RANGE:
1360 err = nvgpu_gpu_clk_get_range(g, priv,
1361 (struct nvgpu_gpu_clk_range_args *)buf);
1362 break;
1363
1364 case NVGPU_GPU_IOCTL_CLK_GET_VF_POINTS:
1365 err = nvgpu_gpu_clk_get_vf_points(g, priv,
1366 (struct nvgpu_gpu_clk_vf_points_args *)buf);
1367 break;
1368
1369 case NVGPU_GPU_IOCTL_CLK_SET_INFO:
1370 err = nvgpu_gpu_clk_set_info(g, priv,
1371 (struct nvgpu_gpu_clk_set_info_args *)buf);
1372 break;
1373
1374 case NVGPU_GPU_IOCTL_CLK_GET_INFO:
1375 err = nvgpu_gpu_clk_get_info(g, priv,
1376 (struct nvgpu_gpu_clk_get_info_args *)buf);
1377 break;
1378
1053 default: 1379 default:
1054 dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd); 1380 dev_dbg(dev_from_gk20a(g), "unrecognized gpu ioctl cmd: 0x%x", cmd);
1055 err = -ENOTTY; 1381 err = -ENOTTY;
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index 99d2fe63..03bbf72f 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -974,6 +974,12 @@ int gk20a_pm_finalize_poweron(struct device *dev)
974 } 974 }
975#endif 975#endif
976 976
977 err = nvgpu_clk_arb_init_arbiter(g);
978 if (err) {
979 gk20a_err(dev, "failed to init clk arb");
980 goto done;
981 }
982
977 if (g->ops.pmu.is_pmu_supported(g)) { 983 if (g->ops.pmu.is_pmu_supported(g)) {
978 err = gk20a_init_pmu_support(g); 984 err = gk20a_init_pmu_support(g);
979 if (err) { 985 if (err) {
@@ -1644,6 +1650,8 @@ static int __exit gk20a_remove(struct platform_device *pdev)
1644 if (platform->has_ce) 1650 if (platform->has_ce)
1645 gk20a_ce_destroy(g); 1651 gk20a_ce_destroy(g);
1646 1652
1653 nvgpu_clk_arb_cleanup_arbiter(g);
1654
1647 gk20a_user_deinit(dev, &nvgpu_class); 1655 gk20a_user_deinit(dev, &nvgpu_class);
1648 1656
1649 debugfs_remove_recursive(platform->debugfs); 1657 debugfs_remove_recursive(platform->debugfs);
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index 024be4db..564026a4 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -56,6 +56,7 @@ struct acr_desc;
56#include "gm206/bios_gm206.h" 56#include "gm206/bios_gm206.h"
57#ifdef CONFIG_ARCH_TEGRA_18x_SOC 57#ifdef CONFIG_ARCH_TEGRA_18x_SOC
58#include "clk/clk.h" 58#include "clk/clk.h"
59#include "clk/clk_arb.h"
59#include "perf/perf.h" 60#include "perf/perf.h"
60#include "pmgr/pmgr.h" 61#include "pmgr/pmgr.h"
61#include "therm/thrm.h" 62#include "therm/thrm.h"
@@ -632,6 +633,13 @@ struct gpu_ops {
632 int (*suspend_clk_support)(struct gk20a *g); 633 int (*suspend_clk_support)(struct gk20a *g);
633 u32 (*get_crystal_clk_hz)(struct gk20a *g); 634 u32 (*get_crystal_clk_hz)(struct gk20a *g);
634 } clk; 635 } clk;
636 struct {
637 u32 (*get_arbiter_clk_domains)(struct gk20a *g);
638 int (*get_arbiter_clk_range)(struct gk20a *g, u32 api_domain,
639 u16 *min_mhz, u16 *max_mhz);
640 int (*get_arbiter_clk_default)(struct gk20a *g, u32 api_domain,
641 u16 *default_mhz);
642 } clk_arb;
635 bool privsecurity; 643 bool privsecurity;
636 bool securegpccs; 644 bool securegpccs;
637 bool pmupstate; 645 bool pmupstate;
@@ -956,6 +964,8 @@ struct gk20a {
956 struct nvgpu_bios bios; 964 struct nvgpu_bios bios;
957 struct debugfs_blob_wrapper bios_blob; 965 struct debugfs_blob_wrapper bios_blob;
958 966
967 struct nvgpu_clk_arb *clk_arb;
968
959 struct gk20a_ce_app ce_app; 969 struct gk20a_ce_app ce_app;
960 970
961 /* PCI device identifier */ 971 /* PCI device identifier */