diff options
author | Debarshi Dutta <ddutta@nvidia.com> | 2019-04-30 04:24:08 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2019-05-09 17:41:30 -0400 |
commit | c81cc032c48a1b25e095b17b77399166c9091ff3 (patch) | |
tree | ace7d238c55bbb5e96fb6fd74deb156f3c513bae /drivers/gpu/nvgpu/os/linux/sysfs.c | |
parent | f495f52c70c6bd7b7a4e6897270e4696efa57d5c (diff) |
gpu: nvgpu: add cg and pg function
Add new power/clock gating functions that can be called by
other units.
New clock_gating functions will reside in cg.c under
common/power_features/cg unit.
New power gating functions will reside in pg.c under
common/power_features/pg unit.
Use nvgpu_pg_elpg_disable and nvgpu_pg_elpg_enable to disable/enable
elpg and also in gr_gk20a_elpg_protected macro to access gr registers.
Add cg_pg_lock to make elpg_enabled, elcg_enabled, blcg_enabled
and slcg_enabled thread safe.
JIRA NVGPU-2014
Change-Id: I00d124c2ee16242c9a3ef82e7620fbb7f1297aff
Signed-off-by: Seema Khowala <seemaj@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2025493
Signed-off-by: Debarshi Dutta <ddutta@nvidia.com>
(cherry-picked from c90585856567a547173a8b207365b3a4a3ccdd57 in
dev-kernel)
Reviewed-on: https://git-master.nvidia.com/r/2108406
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bibek Basu <bbasu@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/sysfs.c')
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/sysfs.c | 137 |
1 files changed, 34 insertions, 103 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/sysfs.c b/drivers/gpu/nvgpu/os/linux/sysfs.c index 1ffb6539..759c12e8 100644 --- a/drivers/gpu/nvgpu/os/linux/sysfs.c +++ b/drivers/gpu/nvgpu/os/linux/sysfs.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <nvgpu/kmem.h> | 21 | #include <nvgpu/kmem.h> |
22 | #include <nvgpu/nvhost.h> | 22 | #include <nvgpu/nvhost.h> |
23 | #include <nvgpu/ptimer.h> | 23 | #include <nvgpu/ptimer.h> |
24 | #include <nvgpu/power_features/cg.h> | ||
25 | #include <nvgpu/power_features/pg.h> | ||
24 | 26 | ||
25 | #include "os_linux.h" | 27 | #include "os_linux.h" |
26 | #include "sysfs.h" | 28 | #include "sysfs.h" |
@@ -49,16 +51,14 @@ static ssize_t elcg_enable_store(struct device *dev, | |||
49 | return err; | 51 | return err; |
50 | 52 | ||
51 | if (val) { | 53 | if (val) { |
52 | g->elcg_enabled = true; | 54 | nvgpu_cg_elcg_set_elcg_enabled(g, true); |
53 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO); | ||
54 | } else { | 55 | } else { |
55 | g->elcg_enabled = false; | 56 | nvgpu_cg_elcg_set_elcg_enabled(g, false); |
56 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); | ||
57 | } | 57 | } |
58 | 58 | ||
59 | gk20a_idle(g); | 59 | gk20a_idle(g); |
60 | 60 | ||
61 | nvgpu_info(g, "ELCG is %s.", g->elcg_enabled ? "enabled" : | 61 | nvgpu_info(g, "ELCG is %s.", val ? "enabled" : |
62 | "disabled"); | 62 | "disabled"); |
63 | 63 | ||
64 | return count; | 64 | return count; |
@@ -84,45 +84,19 @@ static ssize_t blcg_enable_store(struct device *dev, | |||
84 | if (kstrtoul(buf, 10, &val) < 0) | 84 | if (kstrtoul(buf, 10, &val) < 0) |
85 | return -EINVAL; | 85 | return -EINVAL; |
86 | 86 | ||
87 | if (val) | ||
88 | g->blcg_enabled = true; | ||
89 | else | ||
90 | g->blcg_enabled = false; | ||
91 | |||
92 | err = gk20a_busy(g); | 87 | err = gk20a_busy(g); |
93 | if (err) | 88 | if (err) |
94 | return err; | 89 | return err; |
95 | 90 | ||
96 | if (g->ops.clock_gating.blcg_bus_load_gating_prod) | 91 | if (val) { |
97 | g->ops.clock_gating.blcg_bus_load_gating_prod(g, | 92 | nvgpu_cg_blcg_set_blcg_enabled(g, true); |
98 | g->blcg_enabled); | 93 | } else { |
99 | if (g->ops.clock_gating.blcg_ce_load_gating_prod) | 94 | nvgpu_cg_blcg_set_blcg_enabled(g, false); |
100 | g->ops.clock_gating.blcg_ce_load_gating_prod(g, | 95 | } |
101 | g->blcg_enabled); | 96 | |
102 | if (g->ops.clock_gating.blcg_ctxsw_firmware_load_gating_prod) | ||
103 | g->ops.clock_gating.blcg_ctxsw_firmware_load_gating_prod(g, | ||
104 | g->blcg_enabled); | ||
105 | if (g->ops.clock_gating.blcg_fb_load_gating_prod) | ||
106 | g->ops.clock_gating.blcg_fb_load_gating_prod(g, | ||
107 | g->blcg_enabled); | ||
108 | if (g->ops.clock_gating.blcg_fifo_load_gating_prod) | ||
109 | g->ops.clock_gating.blcg_fifo_load_gating_prod(g, | ||
110 | g->blcg_enabled); | ||
111 | if (g->ops.clock_gating.blcg_gr_load_gating_prod) | ||
112 | g->ops.clock_gating.blcg_gr_load_gating_prod(g, | ||
113 | g->blcg_enabled); | ||
114 | if (g->ops.clock_gating.blcg_ltc_load_gating_prod) | ||
115 | g->ops.clock_gating.blcg_ltc_load_gating_prod(g, | ||
116 | g->blcg_enabled); | ||
117 | if (g->ops.clock_gating.blcg_pmu_load_gating_prod) | ||
118 | g->ops.clock_gating.blcg_pmu_load_gating_prod(g, | ||
119 | g->blcg_enabled); | ||
120 | if (g->ops.clock_gating.blcg_xbar_load_gating_prod) | ||
121 | g->ops.clock_gating.blcg_xbar_load_gating_prod(g, | ||
122 | g->blcg_enabled); | ||
123 | gk20a_idle(g); | 97 | gk20a_idle(g); |
124 | 98 | ||
125 | nvgpu_info(g, "BLCG is %s.", g->blcg_enabled ? "enabled" : | 99 | nvgpu_info(g, "BLCG is %s.", val ? "enabled" : |
126 | "disabled"); | 100 | "disabled"); |
127 | 101 | ||
128 | return count; | 102 | return count; |
@@ -149,59 +123,25 @@ static ssize_t slcg_enable_store(struct device *dev, | |||
149 | if (kstrtoul(buf, 10, &val) < 0) | 123 | if (kstrtoul(buf, 10, &val) < 0) |
150 | return -EINVAL; | 124 | return -EINVAL; |
151 | 125 | ||
152 | if (val) | 126 | err = gk20a_busy(g); |
153 | g->slcg_enabled = true; | 127 | if (err) { |
154 | else | 128 | return err; |
155 | g->slcg_enabled = false; | 129 | } |
130 | |||
131 | if (val) { | ||
132 | nvgpu_cg_slcg_set_slcg_enabled(g, true); | ||
133 | } else { | ||
134 | nvgpu_cg_slcg_set_slcg_enabled(g, false); | ||
135 | } | ||
156 | 136 | ||
157 | /* | 137 | /* |
158 | * TODO: slcg_therm_load_gating is not enabled anywhere during | 138 | * TODO: slcg_therm_load_gating is not enabled anywhere during |
159 | * init. Therefore, it would be incongruous to add it here. Once | 139 | * init. Therefore, it would be incongruous to add it here. Once |
160 | * it is added to init, we should add it here too. | 140 | * it is added to init, we should add it here too. |
161 | */ | 141 | */ |
162 | err = gk20a_busy(g); | ||
163 | if (err) | ||
164 | return err; | ||
165 | |||
166 | if (g->ops.clock_gating.slcg_bus_load_gating_prod) | ||
167 | g->ops.clock_gating.slcg_bus_load_gating_prod(g, | ||
168 | g->slcg_enabled); | ||
169 | if (g->ops.clock_gating.slcg_ce2_load_gating_prod) | ||
170 | g->ops.clock_gating.slcg_ce2_load_gating_prod(g, | ||
171 | g->slcg_enabled); | ||
172 | if (g->ops.clock_gating.slcg_chiplet_load_gating_prod) | ||
173 | g->ops.clock_gating.slcg_chiplet_load_gating_prod(g, | ||
174 | g->slcg_enabled); | ||
175 | if (g->ops.clock_gating.slcg_ctxsw_firmware_load_gating_prod) | ||
176 | g->ops.clock_gating.slcg_ctxsw_firmware_load_gating_prod(g, | ||
177 | g->slcg_enabled); | ||
178 | if (g->ops.clock_gating.slcg_fb_load_gating_prod) | ||
179 | g->ops.clock_gating.slcg_fb_load_gating_prod(g, | ||
180 | g->slcg_enabled); | ||
181 | if (g->ops.clock_gating.slcg_fifo_load_gating_prod) | ||
182 | g->ops.clock_gating.slcg_fifo_load_gating_prod(g, | ||
183 | g->slcg_enabled); | ||
184 | if (g->ops.clock_gating.slcg_gr_load_gating_prod) | ||
185 | g->ops.clock_gating.slcg_gr_load_gating_prod(g, | ||
186 | g->slcg_enabled); | ||
187 | if (g->ops.clock_gating.slcg_ltc_load_gating_prod) | ||
188 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, | ||
189 | g->slcg_enabled); | ||
190 | if (g->ops.clock_gating.slcg_perf_load_gating_prod) | ||
191 | g->ops.clock_gating.slcg_perf_load_gating_prod(g, | ||
192 | g->slcg_enabled); | ||
193 | if (g->ops.clock_gating.slcg_priring_load_gating_prod) | ||
194 | g->ops.clock_gating.slcg_priring_load_gating_prod(g, | ||
195 | g->slcg_enabled); | ||
196 | if (g->ops.clock_gating.slcg_pmu_load_gating_prod) | ||
197 | g->ops.clock_gating.slcg_pmu_load_gating_prod(g, | ||
198 | g->slcg_enabled); | ||
199 | if (g->ops.clock_gating.slcg_xbar_load_gating_prod) | ||
200 | g->ops.clock_gating.slcg_xbar_load_gating_prod(g, | ||
201 | g->slcg_enabled); | ||
202 | gk20a_idle(g); | 142 | gk20a_idle(g); |
203 | 143 | ||
204 | nvgpu_info(g, "SLCG is %s.", g->slcg_enabled ? "enabled" : | 144 | nvgpu_info(g, "SLCG is %s.", val ? "enabled" : |
205 | "disabled"); | 145 | "disabled"); |
206 | 146 | ||
207 | return count; | 147 | return count; |
@@ -474,7 +414,7 @@ static ssize_t elpg_enable_store(struct device *dev, | |||
474 | return -EINVAL; | 414 | return -EINVAL; |
475 | 415 | ||
476 | if (!g->power_on) { | 416 | if (!g->power_on) { |
477 | g->elpg_enabled = val ? true : false; | 417 | return -EINVAL; |
478 | } else { | 418 | } else { |
479 | err = gk20a_busy(g); | 419 | err = gk20a_busy(g); |
480 | if (err) | 420 | if (err) |
@@ -483,25 +423,14 @@ static ssize_t elpg_enable_store(struct device *dev, | |||
483 | * Since elpg is refcounted, we should not unnecessarily call | 423 | * Since elpg is refcounted, we should not unnecessarily call |
484 | * enable/disable if it is already so. | 424 | * enable/disable if it is already so. |
485 | */ | 425 | */ |
486 | if (val && !g->elpg_enabled) { | 426 | if (val != 0) { |
487 | g->elpg_enabled = true; | 427 | nvgpu_pg_elpg_set_elpg_enabled(g, true); |
488 | nvgpu_pmu_pg_global_enable(g, true); | 428 | } else { |
489 | 429 | nvgpu_pg_elpg_set_elpg_enabled(g, false); | |
490 | } else if (!val && g->elpg_enabled) { | ||
491 | if (g->ops.pmu.pmu_pg_engines_feature_list && | ||
492 | g->ops.pmu.pmu_pg_engines_feature_list(g, | ||
493 | PMU_PG_ELPG_ENGINE_ID_GRAPHICS) != | ||
494 | NVGPU_PMU_GR_FEATURE_MASK_POWER_GATING) { | ||
495 | nvgpu_pmu_pg_global_enable(g, false); | ||
496 | g->elpg_enabled = false; | ||
497 | } else { | ||
498 | g->elpg_enabled = false; | ||
499 | nvgpu_pmu_pg_global_enable(g, false); | ||
500 | } | ||
501 | } | 430 | } |
502 | gk20a_idle(g); | 431 | gk20a_idle(g); |
503 | } | 432 | } |
504 | nvgpu_info(g, "ELPG is %s.", g->elpg_enabled ? "enabled" : | 433 | nvgpu_info(g, "ELPG is %s.", val ? "enabled" : |
505 | "disabled"); | 434 | "disabled"); |
506 | 435 | ||
507 | return count; | 436 | return count; |
@@ -512,7 +441,8 @@ static ssize_t elpg_enable_read(struct device *dev, | |||
512 | { | 441 | { |
513 | struct gk20a *g = get_gk20a(dev); | 442 | struct gk20a *g = get_gk20a(dev); |
514 | 443 | ||
515 | return snprintf(buf, PAGE_SIZE, "%d\n", g->elpg_enabled ? 1 : 0); | 444 | return snprintf(buf, PAGE_SIZE, "%d\n", |
445 | nvgpu_pg_elpg_is_enabled(g) ? 1 : 0); | ||
516 | } | 446 | } |
517 | 447 | ||
518 | static DEVICE_ATTR(elpg_enable, ROOTRW, elpg_enable_read, elpg_enable_store); | 448 | static DEVICE_ATTR(elpg_enable, ROOTRW, elpg_enable_read, elpg_enable_store); |
@@ -610,8 +540,9 @@ static ssize_t mscg_enable_store(struct device *dev, | |||
610 | /* make status visible */ | 540 | /* make status visible */ |
611 | smp_mb(); | 541 | smp_mb(); |
612 | g->mscg_enabled = false; | 542 | g->mscg_enabled = false; |
613 | if (g->elpg_enabled) | 543 | if (nvgpu_pg_elpg_is_enabled(g)) { |
614 | nvgpu_pmu_pg_global_enable(g, true); | 544 | nvgpu_pg_elpg_enable(g); |
545 | } | ||
615 | } | 546 | } |
616 | g->mscg_enabled = false; | 547 | g->mscg_enabled = false; |
617 | } | 548 | } |