diff options
author | Deepak Goyal <dgoyal@nvidia.com> | 2018-07-16 01:40:23 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-07-24 02:52:39 -0400 |
commit | d3b8415948de8c9ffe2f2fa66340dd7e71a894e6 (patch) | |
tree | 328970819ace31fae3bf3bc27376121330064db9 /drivers/gpu/nvgpu/os/linux | |
parent | 2df33e32e40eb2c8e025f8d27396d9b5cdb3ac11 (diff) |
gpu: nvgpu: tpc powergating through sysfs
- adds static tpc-powergating through sysfs.
- active tpc count will remain till the GPU/systems is not booted again.
- tpc_pg_mask can be written only after GPU probe finishes and
GPU boot is triggered.
Note:
To be able to use this feature, we need to change boot/init
scripts of the OS(used with nvgpu driver) to write to sysfs nodes before
posting discover image size query to FECS.
Bug 200406784
Change-Id: Id749c7a617422c625f77d0c1a9aada2eb960c4d0
Signed-off-by: Deepak Goyal <dgoyal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1742422
Reviewed-by: svc-misra-checker <svc-misra-checker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux')
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/driver_common.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/platform_gk20a.h | 5 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/sysfs.c | 59 |
4 files changed, 70 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index 8a7cf552..c651e394 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c | |||
@@ -64,6 +64,7 @@ static void nvgpu_init_vars(struct gk20a *g) | |||
64 | nvgpu_mutex_init(&g->poweron_lock); | 64 | nvgpu_mutex_init(&g->poweron_lock); |
65 | nvgpu_mutex_init(&g->poweroff_lock); | 65 | nvgpu_mutex_init(&g->poweroff_lock); |
66 | nvgpu_mutex_init(&g->ctxsw_disable_lock); | 66 | nvgpu_mutex_init(&g->ctxsw_disable_lock); |
67 | nvgpu_mutex_init(&g->tpc_pg_lock); | ||
67 | 68 | ||
68 | l->regs_saved = l->regs; | 69 | l->regs_saved = l->regs; |
69 | l->bar1_saved = l->bar1; | 70 | l->bar1_saved = l->bar1; |
@@ -168,6 +169,8 @@ static void nvgpu_init_pm_vars(struct gk20a *g) | |||
168 | g->ptimer_src_freq = platform->ptimer_src_freq; | 169 | g->ptimer_src_freq = platform->ptimer_src_freq; |
169 | g->support_pmu = support_gk20a_pmu(dev_from_gk20a(g)); | 170 | g->support_pmu = support_gk20a_pmu(dev_from_gk20a(g)); |
170 | __nvgpu_set_enabled(g, NVGPU_CAN_RAILGATE, platform->can_railgate_init); | 171 | __nvgpu_set_enabled(g, NVGPU_CAN_RAILGATE, platform->can_railgate_init); |
172 | g->can_tpc_powergate = platform->can_tpc_powergate; | ||
173 | g->valid_tpc_mask = platform->valid_tpc_mask; | ||
171 | g->ldiv_slowdown_factor = platform->ldiv_slowdown_factor_init; | 174 | g->ldiv_slowdown_factor = platform->ldiv_slowdown_factor_init; |
172 | /* if default delay is not set, set default delay to 500msec */ | 175 | /* if default delay is not set, set default delay to 500msec */ |
173 | if (platform->railgate_delay_init) | 176 | if (platform->railgate_delay_init) |
diff --git a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h index d9725e4c..a4c3eca3 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h +++ b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h | |||
@@ -44,6 +44,9 @@ struct gk20a_platform { | |||
44 | bool can_railgate_init; | 44 | bool can_railgate_init; |
45 | 45 | ||
46 | /* Should be populated at probe. */ | 46 | /* Should be populated at probe. */ |
47 | bool can_tpc_powergate; | ||
48 | |||
49 | /* Should be populated at probe. */ | ||
47 | bool can_elpg_init; | 50 | bool can_elpg_init; |
48 | 51 | ||
49 | /* Should be populated at probe. */ | 52 | /* Should be populated at probe. */ |
@@ -71,6 +74,8 @@ struct gk20a_platform { | |||
71 | /* Reset control for device */ | 74 | /* Reset control for device */ |
72 | struct reset_control *reset_control; | 75 | struct reset_control *reset_control; |
73 | #endif | 76 | #endif |
77 | /* valid TPC-MASK */ | ||
78 | u32 valid_tpc_mask; | ||
74 | 79 | ||
75 | /* Delay before rail gated */ | 80 | /* Delay before rail gated */ |
76 | int railgate_delay_init; | 81 | int railgate_delay_init; |
diff --git a/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c index c9c13197..edb3263c 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/platform_gv11b_tegra.c | |||
@@ -209,6 +209,9 @@ struct gk20a_platform gv11b_tegra_platform = { | |||
209 | .railgate_delay_init = 500, | 209 | .railgate_delay_init = 500, |
210 | .can_railgate_init = true, | 210 | .can_railgate_init = true, |
211 | 211 | ||
212 | .can_tpc_powergate = true, | ||
213 | .valid_tpc_mask = 0xc, | ||
214 | |||
212 | .can_slcg = true, | 215 | .can_slcg = true, |
213 | .can_blcg = true, | 216 | .can_blcg = true, |
214 | .can_elcg = true, | 217 | .can_elcg = true, |
diff --git a/drivers/gpu/nvgpu/os/linux/sysfs.c b/drivers/gpu/nvgpu/os/linux/sysfs.c index 1b84e2e2..b607768a 100644 --- a/drivers/gpu/nvgpu/os/linux/sysfs.c +++ b/drivers/gpu/nvgpu/os/linux/sysfs.c | |||
@@ -31,6 +31,8 @@ | |||
31 | 31 | ||
32 | #define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH) | 32 | #define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH) |
33 | 33 | ||
34 | #define TPC_MASK_FOR_ALL_ACTIVE_TPCs (u32) 0x0 | ||
35 | |||
34 | static ssize_t elcg_enable_store(struct device *dev, | 36 | static ssize_t elcg_enable_store(struct device *dev, |
35 | struct device_attribute *attr, const char *buf, size_t count) | 37 | struct device_attribute *attr, const char *buf, size_t count) |
36 | { | 38 | { |
@@ -843,6 +845,61 @@ static ssize_t force_idle_read(struct device *dev, | |||
843 | static DEVICE_ATTR(force_idle, ROOTRW, force_idle_read, force_idle_store); | 845 | static DEVICE_ATTR(force_idle, ROOTRW, force_idle_read, force_idle_store); |
844 | #endif | 846 | #endif |
845 | 847 | ||
848 | static ssize_t tpc_pg_mask_read(struct device *dev, | ||
849 | struct device_attribute *attr, char *buf) | ||
850 | { | ||
851 | struct gk20a *g = get_gk20a(dev); | ||
852 | |||
853 | return snprintf(buf, PAGE_SIZE, "%d\n", g->tpc_pg_mask); | ||
854 | } | ||
855 | |||
856 | static ssize_t tpc_pg_mask_store(struct device *dev, | ||
857 | struct device_attribute *attr, const char *buf, size_t count) | ||
858 | { | ||
859 | struct gk20a *g = get_gk20a(dev); | ||
860 | struct gr_gk20a *gr = &g->gr; | ||
861 | unsigned long val = 0; | ||
862 | |||
863 | nvgpu_mutex_acquire(&g->tpc_pg_lock); | ||
864 | |||
865 | if (!g->can_tpc_powergate) { | ||
866 | nvgpu_info(g, "TPC-PG not enabled for the platform"); | ||
867 | goto exit; | ||
868 | } | ||
869 | |||
870 | if (kstrtoul(buf, 10, &val) < 0) { | ||
871 | nvgpu_err(g, "invalid value"); | ||
872 | nvgpu_mutex_release(&g->tpc_pg_lock); | ||
873 | return -EINVAL; | ||
874 | } | ||
875 | |||
876 | if (val == g->tpc_pg_mask) { | ||
877 | nvgpu_info(g, "no value change, same mask already set"); | ||
878 | goto exit; | ||
879 | } | ||
880 | |||
881 | if (gr->ctx_vars.golden_image_size) { | ||
882 | nvgpu_err(g, "golden image size already initialized"); | ||
883 | nvgpu_mutex_release(&g->tpc_pg_lock); | ||
884 | return -ENODEV; | ||
885 | } | ||
886 | |||
887 | if (val == TPC_MASK_FOR_ALL_ACTIVE_TPCs || val == g->valid_tpc_mask) { | ||
888 | g->tpc_pg_mask = val; | ||
889 | } else { | ||
890 | |||
891 | nvgpu_err(g, "TPC-PG mask is invalid"); | ||
892 | nvgpu_mutex_release(&g->tpc_pg_lock); | ||
893 | return -EINVAL; | ||
894 | } | ||
895 | exit: | ||
896 | nvgpu_mutex_release(&g->tpc_pg_lock); | ||
897 | |||
898 | return count; | ||
899 | } | ||
900 | |||
901 | static DEVICE_ATTR(tpc_pg_mask, ROOTRW, tpc_pg_mask_read, tpc_pg_mask_store); | ||
902 | |||
846 | static ssize_t tpc_fs_mask_store(struct device *dev, | 903 | static ssize_t tpc_fs_mask_store(struct device *dev, |
847 | struct device_attribute *attr, const char *buf, size_t count) | 904 | struct device_attribute *attr, const char *buf, size_t count) |
848 | { | 905 | { |
@@ -1130,6 +1187,7 @@ void nvgpu_remove_sysfs(struct device *dev) | |||
1130 | device_remove_file(dev, &dev_attr_aelpg_enable); | 1187 | device_remove_file(dev, &dev_attr_aelpg_enable); |
1131 | device_remove_file(dev, &dev_attr_allow_all); | 1188 | device_remove_file(dev, &dev_attr_allow_all); |
1132 | device_remove_file(dev, &dev_attr_tpc_fs_mask); | 1189 | device_remove_file(dev, &dev_attr_tpc_fs_mask); |
1190 | device_remove_file(dev, &dev_attr_tpc_pg_mask); | ||
1133 | device_remove_file(dev, &dev_attr_min_timeslice_us); | 1191 | device_remove_file(dev, &dev_attr_min_timeslice_us); |
1134 | device_remove_file(dev, &dev_attr_max_timeslice_us); | 1192 | device_remove_file(dev, &dev_attr_max_timeslice_us); |
1135 | 1193 | ||
@@ -1181,6 +1239,7 @@ int nvgpu_create_sysfs(struct device *dev) | |||
1181 | error |= device_create_file(dev, &dev_attr_aelpg_enable); | 1239 | error |= device_create_file(dev, &dev_attr_aelpg_enable); |
1182 | error |= device_create_file(dev, &dev_attr_allow_all); | 1240 | error |= device_create_file(dev, &dev_attr_allow_all); |
1183 | error |= device_create_file(dev, &dev_attr_tpc_fs_mask); | 1241 | error |= device_create_file(dev, &dev_attr_tpc_fs_mask); |
1242 | error |= device_create_file(dev, &dev_attr_tpc_pg_mask); | ||
1184 | error |= device_create_file(dev, &dev_attr_min_timeslice_us); | 1243 | error |= device_create_file(dev, &dev_attr_min_timeslice_us); |
1185 | error |= device_create_file(dev, &dev_attr_max_timeslice_us); | 1244 | error |= device_create_file(dev, &dev_attr_max_timeslice_us); |
1186 | 1245 | ||