aboutsummaryrefslogtreecommitdiffstats
path: root/runlist.c
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2024-09-19 12:50:02 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2024-09-19 13:59:56 -0400
commit48f9e45b9d9ebfca7d3c673597f7fbed9427a5af (patch)
treed63c3863e9b187fb1f62d2f3c58b8c6a9568b6cc /runlist.c
parentac0113ab52d2ca12a5c10feeaa887d10c37ee4f1 (diff)
Ampere: disable/enable_channel, preempt/switch_to_tsg, and resubmit_runlist
**Modifes the user API from `echo 1 > /proc/gpuX/switch_to_tsg` to `echo 1 > /proc/gpuX/runlist0/switch_to_tsg` to switch to TSG 1 on runlist 0 on GPU X for pre-Ampere GPUs (for example).** Feature changes: - switch_to_tsg only makes sense on a per-runlist level. Before, this always operated on runlist0; this commit allows operating on any runlist by moving the API to the per-runlist paths. - On Ampere+, channel and TSG IDs are per-runlist, and no longer GPU-global. Consequently, the disable/enable_channel and preempt_tsg APIs have been moved from GPU-global to per-runlist paths on Ampere+. Bug fixes: - `preempt_runlist()` is now supported on Maxwell and Pascal. - `resubmit_runlist()` detects too-old GPUs. - MAX_CHID corrected from 512 to 511 and documented. - switch_to_tsg now includes a runlist resubmit, which appears to be necessary on Turing+ GPUs. Tested on GK104 (Quadro K5000), GM204 (GTX 970), GP106 (GTX 1060 3GB), GP104 (GTX 1080 Ti), GP10B (Jetson TX2), GV11B (Jetson Xavier), GV100 (Titan V), TU102 (RTX 2080 Ti), and AD102 (RTX 6000 Ada).
Diffstat (limited to 'runlist.c')
-rw-r--r--runlist.c69
1 files changed, 56 insertions, 13 deletions
diff --git a/runlist.c b/runlist.c
index 7e6d292..7bb2ee4 100644
--- a/runlist.c
+++ b/runlist.c
@@ -169,24 +169,35 @@ attempt_pramin_access:
169 169
170/* Trigger a preempt of the specified TSG 170/* Trigger a preempt of the specified TSG
171 @param tsg_id ID of TSG to preempt. 171 @param tsg_id ID of TSG to preempt.
172 @param rl_id Which channel RAM address space to search?
172 @return 0 or -errno on error 173 @return 0 or -errno on error
173 174
174 Note: If no other TSGs exist in the associated runlist, this TSG may 175 Note: If no other TSGs exist in the associated runlist, this TSG may
175 continue executing, unless NV_PFIFO_SCHED_DISABLE is set, or all the 176 continue executing, unless NV_PFIFO_SCHED_DISABLE is set, or all the
176 channels of the TSG to be preempted are disabled. 177 channels of the TSG to be preempted are disabled.
177*/ 178*/
178int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id) { 179int preempt_tsg(struct nvdebug_state *g, uint32_t rl_id, uint32_t tsg_id) {
179 pfifo_preempt_t pfifo_preempt; 180 pfifo_preempt_t preempt;
181 // Fermi does not support time-slice groups
180 if (g->chip_id < NV_CHIP_ID_KEPLER) 182 if (g->chip_id < NV_CHIP_ID_KEPLER)
181 return -EOPNOTSUPP; 183 return -EOPNOTSUPP;
182 184
183 pfifo_preempt.raw = 0; 185 preempt.raw = 0;
184 pfifo_preempt.id = tsg_id; 186 preempt.id = tsg_id;
185 pfifo_preempt.is_pending = 0; 187 preempt.type = PREEMPT_TYPE_TSG;
186 pfifo_preempt.type = PREEMPT_TYPE_TSG;
187 188
188 // Actually trigger the preemption 189 // Actually trigger the preemption
189 nvdebug_writel(g, NV_PFIFO_PREEMPT, pfifo_preempt.raw); 190 if (g->chip_id < NV_CHIP_ID_AMPERE) {
191 nvdebug_writel(g, NV_PFIFO_PREEMPT, preempt.raw);
192 } else {
193 uint32_t runlist_reg_base;
194 int err;
195 // As TSG and channel IDs are namespaced per-runlist starting with
196 // Ampere, the PREEMPT register is also per-runlist.
197 if ((err = get_runlist_ram(g, rl_id, &runlist_reg_base)))
198 return err;
199 nvdebug_writel(g, runlist_reg_base + NV_RUNLIST_PREEMPT_GA100, preempt.raw);
200 }
190 return 0; 201 return 0;
191} 202}
192 203
@@ -195,18 +206,38 @@ int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id) {
195 @return 0 or -errno on error 206 @return 0 or -errno on error
196*/ 207*/
197int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id) { 208int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id) {
198 runlist_preempt_t rl_preempt; 209 // The runlist preempt register does not exist on Kepler (tested gk104)
199 if (g->chip_id < NV_CHIP_ID_VOLTA) 210 if (g->chip_id < NV_CHIP_ID_MAXWELL)
200 return -EOPNOTSUPP; 211 return -EOPNOTSUPP;
201 212
202 // Overwrite, as the register contains nothing to preserve 213 // Write to trigger the preemption (the register contains nothing to
203 rl_preempt.raw = BIT(rl_id); 214 // preserve, and can thus just be overwritten)
204 nvdebug_writel(g, NV_PFIFO_RUNLIST_PREEMPT, rl_preempt.raw); 215 if (g->chip_id < NV_CHIP_ID_AMPERE) {
216 runlist_preempt_t rl_preempt;
217 rl_preempt.raw = BIT(rl_id);
218 nvdebug_writel(g, NV_PFIFO_RUNLIST_PREEMPT, rl_preempt.raw);
219 } else {
220 int err;
221 uint32_t runlist_regs_base;
222 pfifo_preempt_t preempt;
223 // The RUNLIST_PREEMPT register was deleted, and the _PREEMPT register
224 // was extended to support runlist-level preemptions starting on Ampere
225 preempt.id = rl_id;
226 preempt.type = PREEMPT_TYPE_RUNLIST;
227 // The preempt register is scoped per-runlist on Ampere+
228 if ((err = get_runlist_ram(g, rl_id, &runlist_regs_base)))
229 return err;
230 nvdebug_writel(g, runlist_regs_base + NV_RUNLIST_PREEMPT_GA100, preempt.raw);
231 }
205 return 0; 232 return 0;
206} 233}
207 234
208// Read and write runlist configuration, triggering a resubmit 235// Read and write runlist configuration, triggering a resubmit
209int resubmit_runlist(struct nvdebug_state *g, uint32_t rl_id) { 236int resubmit_runlist(struct nvdebug_state *g, uint32_t rl_id) {
237 // Necessary registers do not exist pre-Fermi
238 if (g->chip_id < NV_CHIP_ID_FERMI)
239 return -EOPNOTSUPP;
240
210 if (g->chip_id < NV_CHIP_ID_TURING) { 241 if (g->chip_id < NV_CHIP_ID_TURING) {
211 eng_runlist_gf100_t rl; 242 eng_runlist_gf100_t rl;
212 if (rl_id > MAX_RUNLISTS_GF100) 243 if (rl_id > MAX_RUNLISTS_GF100)
@@ -223,7 +254,19 @@ int resubmit_runlist(struct nvdebug_state *g, uint32_t rl_id) {
223 return -EIO; 254 return -EIO;
224 nvdebug_writeq(g, NV_PFIFO_RUNLIST_SUBMIT_TU102(rl_id), submit.raw); 255 nvdebug_writeq(g, NV_PFIFO_RUNLIST_SUBMIT_TU102(rl_id), submit.raw);
225 } else { 256 } else {
226 return -EOPNOTSUPP; 257 int err;
258 uint32_t runlist_pri_base;
259 runlist_submit_tu102_t submit;
260 if ((err = get_runlist_ram(g, rl_id, &runlist_pri_base)) < 0)
261 return err;
262 if ((submit.raw = nvdebug_readq(g, runlist_pri_base + NV_RUNLIST_SUBMIT_GA100)) == -1)
263 return -EIO;
264 // On Ampere, this does not appear to trigger a preempt of the
265 // currently-running channel (even if the currently running channel
266 // becomes disabled), but will cause newly re-enabled channels
267 // (at least if nothing else is pending) to become ready (tested on
268 // Jetson Orin).
269 nvdebug_writeq(g, runlist_pri_base + NV_RUNLIST_SUBMIT_GA100, submit.raw);
227 } 270 }
228 return 0; 271 return 0;
229} 272}