diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2021-09-23 12:49:27 -0400 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2021-09-23 12:49:27 -0400 |
| commit | 0596e479ffcca43957f8d32127cea5527460b983 (patch) | |
| tree | 2ea671a4df3def4a72ac3edbce645ff661150cb7 /runlist_procfs.c | |
| parent | a7564070dcdf75de4f848af936e3d76ed01833e1 (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.c | 135 |
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 | |||
| 155 | ssize_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 | |||
| 175 | const struct file_operations preempt_tsg_file_ops = { | ||
| 176 | .write = preempt_tsg_file_write, | ||
| 177 | }; | ||
| 178 | |||
| 179 | ssize_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 | |||
| 203 | const struct file_operations disable_channel_file_ops = { | ||
| 204 | .write = disable_channel_file_write, | ||
| 205 | }; | ||
| 206 | |||
| 207 | ssize_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 | |||
| 231 | const struct file_operations enable_channel_file_ops = { | ||
| 232 | .write = enable_channel_file_write, | ||
| 233 | }; | ||
| 234 | |||
| 235 | ssize_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 | |||
| 286 | const struct file_operations switch_to_tsg_file_ops = { | ||
| 287 | .write = switch_to_tsg_file_write, | ||
| 288 | }; | ||
