aboutsummaryrefslogtreecommitdiffstats
path: root/runlist.c
diff options
context:
space:
mode:
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}