aboutsummaryrefslogtreecommitdiffstats
path: root/runlist_procfs.c
diff options
context:
space:
mode:
authorJoshua Bakita <jbakita@cs.unc.edu>2021-09-23 12:49:27 -0400
committerJoshua Bakita <jbakita@cs.unc.edu>2021-09-23 12:49:27 -0400
commit0596e479ffcca43957f8d32127cea5527460b983 (patch)
tree2ea671a4df3def4a72ac3edbce645ff661150cb7 /runlist_procfs.c
parenta7564070dcdf75de4f848af936e3d76ed01833e1 (diff)
Add APIs to enable/disable a channel and switch to or preempt a specific TSG
Adds: - /proc/preempt_tsg which takes a TSG ID - /proc/disable_channel which takes a channel ID - /proc/enable_channel which takes a channel ID - /proc/switch_to_tsg which takes a TSG ID Also significantly expands documentation and structs available in nvdebug.h.
Diffstat (limited to 'runlist_procfs.c')
-rw-r--r--runlist_procfs.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/runlist_procfs.c b/runlist_procfs.c
index 183eab6..411f844 100644
--- a/runlist_procfs.c
+++ b/runlist_procfs.c
@@ -151,3 +151,138 @@ const struct file_operations runlist_file_ops = {
151 .llseek = seq_lseek, 151 .llseek = seq_lseek,
152 .release = seq_release, 152 .release = seq_release,
153}; 153};
154
155ssize_t preempt_tsg_file_write(struct file *f, const char __user *buffer,
156 size_t count, loff_t *off) {
157 uint32_t target_tsgid;
158 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
159 int err = kstrtou32_from_user(buffer, count, 0, &target_tsgid);
160 if (err)
161 return err;
162
163 // TSG IDs are a 12-bit field, so make sure the request is in-range
164 if (target_tsgid > MAX_TSGID)
165 return -ERANGE;
166
167 // Execute preemption
168 err = preempt_tsg(target_tsgid);
169 if (err)
170 return err;
171
172 return count;
173}
174
175const struct file_operations preempt_tsg_file_ops = {
176 .write = preempt_tsg_file_write,
177};
178
179ssize_t disable_channel_file_write(struct file *f, const char __user *buffer,
180 size_t count, loff_t *off) {
181 uint32_t target_channel;
182 channel_ctrl_t chan;
183 int err;
184 struct gk20a *g = get_live_gk20a();
185 if (!g)
186 return -EIO;
187 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
188 err = kstrtou32_from_user(buffer, count, 0, &target_channel);
189 if (err)
190 return err;
191
192 if (target_channel > MAX_CHID)
193 return -ERANGE;
194
195 // Disable channel
196 chan.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(target_channel));
197 chan.enable_clear = true;
198 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(target_channel), chan.raw);
199
200 return count;
201}
202
203const struct file_operations disable_channel_file_ops = {
204 .write = disable_channel_file_write,
205};
206
207ssize_t enable_channel_file_write(struct file *f, const char __user *buffer,
208 size_t count, loff_t *off) {
209 uint32_t target_channel;
210 channel_ctrl_t chan;
211 int err;
212 struct gk20a *g = get_live_gk20a();
213 if (!g)
214 return -EIO;
215 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
216 err = kstrtou32_from_user(buffer, count, 0, &target_channel);
217 if (err)
218 return err;
219
220 if (target_channel > MAX_CHID)
221 return -ERANGE;
222
223 // Disable channel
224 chan.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(target_channel));
225 chan.enable_set = true;
226 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(target_channel), chan.raw);
227
228 return count;
229}
230
231const struct file_operations enable_channel_file_ops = {
232 .write = enable_channel_file_write,
233};
234
235ssize_t switch_to_tsg_file_write(struct file *f, const char __user *buffer,
236 size_t count, loff_t *off) {
237 uint32_t target_tsgid;
238 struct runlist_chan* chan;
239 channel_ctrl_t chan_ctl;
240 struct runlist_iter rl_iter;
241 int err;
242 loff_t pos = 0;
243 struct gk20a *g = get_live_gk20a();
244 if (!g)
245 return -EIO;
246 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
247 err = kstrtou32_from_user(buffer, count, 0, &target_tsgid);
248 if (err)
249 return err;
250
251 if (target_tsgid > MAX_TSGID)
252 return -ERANGE;
253
254 err = get_runlist_iter(&rl_iter);
255 if (err)
256 return err;
257
258 // Iterate through all TSGs
259 while (pos < rl_iter.rl_info.len) {
260 if (rl_iter.curr_tsg->tsgid == target_tsgid) {
261 // Enable channels of target TSG
262 for_chan_in_tsg(chan, rl_iter.curr_tsg) {
263 chan_ctl.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(chan->chid));
264 chan_ctl.enable_set = true;
265 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(chan->chid), chan_ctl.raw);
266 }
267 } else {
268 // Disable all other channels
269 for_chan_in_tsg(chan, rl_iter.curr_tsg) {
270 chan_ctl.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(chan->chid));
271 chan_ctl.enable_clear = true;
272 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(chan->chid), chan_ctl.raw);
273 }
274 }
275 pos += 1 + rl_iter.curr_tsg->tsg_length;
276 rl_iter.curr_tsg = next_tsg(rl_iter.curr_tsg);
277 }
278 // Switch to next TSG with active channels (should be our TSG)
279 err = preempt_tsg(target_tsgid);
280 if (err)
281 return err;
282
283 return count;
284}
285
286const struct file_operations switch_to_tsg_file_ops = {
287 .write = switch_to_tsg_file_write,
288};