diff options
Diffstat (limited to 'runlist.c')
-rw-r--r-- | runlist.c | 69 |
1 files changed, 56 insertions, 13 deletions
@@ -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 | */ |
178 | int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id) { | 179 | int 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 | */ |
197 | int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id) { | 208 | int 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 |
209 | int resubmit_runlist(struct nvdebug_state *g, uint32_t rl_id) { | 236 | int 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 | } |