aboutsummaryrefslogtreecommitdiffstats
path: root/runlist_procfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'runlist_procfs.c')
-rw-r--r--runlist_procfs.c188
1 files changed, 111 insertions, 77 deletions
diff --git a/runlist_procfs.c b/runlist_procfs.c
index 411f844..a6b0d94 100644
--- a/runlist_procfs.c
+++ b/runlist_procfs.c
@@ -6,7 +6,14 @@
6#define RUNLIST_PROCFS_NAME "runlist" 6#define RUNLIST_PROCFS_NAME "runlist"
7#define DETAILED_CHANNEL_INFO 7#define DETAILED_CHANNEL_INFO
8 8
9static int runlist_detail_seq_show_chan(struct seq_file *s, struct gk20a *g, uint32_t chid) { 9/* Print channel details using PCCSR (Programmable Channel Control System RAM?)
10 * @param s Pointer to state from seq_file subsystem to pass to seq_printf
11 * @param g Pointer to our internal GPU state
12 * @param chid ID of channel to print details on, range [0, 512)
13 * @param prefix Text string to prefix each line with, or empty string
14 */
15#ifdef DETAILED_CHANNEL_INFO
16static int runlist_detail_seq_show_chan(struct seq_file *s, struct nvdebug_state *g, uint32_t chid, char *prefix) {
10 channel_ctrl_t chan; 17 channel_ctrl_t chan;
11 char *loc_txt; 18 char *loc_txt;
12 u64 instance_ptr; 19 u64 instance_ptr;
@@ -16,23 +23,37 @@ static int runlist_detail_seq_show_chan(struct seq_file *s, struct gk20a *g, uin
16 return -EIO; 23 return -EIO;
17 instance_ptr = chan.inst_ptr; 24 instance_ptr = chan.inst_ptr;
18 instance_ptr <<= 12; 25 instance_ptr <<= 12;
19 seq_printf(s, " +- Channel Info %-4d -+\n", chid); 26 seq_printf(s, "%s+- Channel Info %-4d -+\n", prefix, chid);
20 seq_printf(s, " | Enabled: %d|\n", chan.enable); 27 seq_printf(s, "%s| Enabled: %d|\n", prefix, chan.enable);
21 seq_printf(s, " | Next: %d|\n", chan.next); 28 seq_printf(s, "%s| Next: %d|\n", prefix, chan.next);
22 seq_printf(s, " | Force CTX Reload: %d|\n", chan.force_ctx_reload); 29 seq_printf(s, "%s| Force CTX Reload: %d|\n", prefix, chan.force_ctx_reload);
23 seq_printf(s, " | Enable set: %d|\n", chan.enable_set); 30 seq_printf(s, "%s| Enable set: %d|\n", prefix, chan.enable_set);
24 seq_printf(s, " | Enable clear: %d|\n", chan.enable_clear); 31 seq_printf(s, "%s| Enable clear: %d|\n", prefix, chan.enable_clear);
25 seq_printf(s, " | PBDMA Faulted: %d|\n", chan.pbdma_faulted); 32 seq_printf(s, "%s| PBDMA Faulted: %d|\n", prefix, chan.pbdma_faulted);
26 seq_printf(s, " | ENG Faulted: %d|\n", chan.eng_faulted); 33 seq_printf(s, "%s| ENG Faulted: %d|\n", prefix, chan.eng_faulted);
27 seq_printf(s, " | Status: %2d|\n", chan.status); 34 seq_printf(s, "%s| Status: %2d|\n", prefix, chan.status);
28 seq_printf(s, " | Busy: %d|\n", chan.busy); 35 seq_printf(s, "%s| Busy: %d|\n", prefix, chan.busy);
29 seq_printf(s, " | Instance PTR: |\n"); 36 seq_printf(s, "%s| Instance PTR: |\n", prefix);
30 seq_printf(s, " | %#018llx |\n", instance_ptr); 37 seq_printf(s, "%s| %#018llx |\n", prefix, instance_ptr);
31 seq_printf(s, " | %-20s|\n", loc_txt); 38 seq_printf(s, "%s| %-20s|\n", prefix, loc_txt);
32 seq_printf(s, " | Instance bound: %d|\n", chan.inst_bind); 39 seq_printf(s, "%s| Instance bound: %d|\n", prefix, chan.inst_bind);
33 seq_printf(s, " +---------------------+\n"); 40 // START TEMP
41 // "runlist_id -1 is synonym for the ENGINE_GR_GK20A runlist id"
42 // GR, GRCE, and ASYNC_CE
43 // Note that this appears to be broken??
44 // Peek into the channel instance RAM
45 if (chan.inst_target == TARGET_SYS_MEM_COHERENT) {
46 seq_printf(s, "%s| Target Engine: %2d|\n", prefix, *(uint32_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*43/*NV_RAMFC_TARGET*/) & 0x1f);
47 seq_printf(s, "%s| PDB LO: %#08x|\n", prefix, *(uint32_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*128/*NV_RAMIN_PAGE_DIR_BASE_LO*/) & 0xfffff000);
48 seq_printf(s, "%s| Num subcontexts: %2ld|\n", prefix, hweight64(*(uint64_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*166/*NV_RAMIN_SC_PDB_VALID*/)));
49 // This appears to be unset on Xavier
50 //seq_printf(s, "%s| PAS ID: %8ld|\n", prefix, *(uint32_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*135/*NV_RAMIN_PASID*/) & 0xfffff);
51 }
52 // END TEMP
53 seq_printf(s, "%s+---------------------+\n", prefix);
34 return 0; 54 return 0;
35} 55}
56#endif
36 57
37#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) 58#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)
38// Bug workaround. See comment in runlist_file_seq_start() 59// Bug workaround. See comment in runlist_file_seq_start()
@@ -41,10 +62,14 @@ static loff_t pos_fixup;
41 62
42static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) { 63static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) {
43 static struct runlist_iter rl_iter; 64 static struct runlist_iter rl_iter;
65 struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(s->file)];
44 // *pos == 0 for first call after read of file 66 // *pos == 0 for first call after read of file
45 if (*pos == 0) { 67 if (*pos == 0) {
46 int err = get_runlist_iter(&rl_iter); 68 int err = get_runlist_iter(g, seq2gpuidx(s), &rl_iter);
47 if (err) 69 if (err)
70 return ERR_PTR(err);
71 // Don't try to print an empty runlist
72 if (rl_iter.rl_info.len <= 0)
48 return NULL; 73 return NULL;
49 return &rl_iter; 74 return &rl_iter;
50 } 75 }
@@ -68,12 +93,13 @@ static void* runlist_file_seq_next(struct seq_file *s, void *raw_rl_iter,
68 loff_t *pos) { 93 loff_t *pos) {
69 struct runlist_iter* rl_iter = raw_rl_iter; 94 struct runlist_iter* rl_iter = raw_rl_iter;
70 void *ret = NULL; 95 void *ret = NULL;
71 // Advance by one TSG + channels under last TSG 96 struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(s->file)];
72 *pos += 1 + rl_iter->curr_tsg->tsg_length; 97 // Advance by one TSG or channel
98 (*pos)++;
99 rl_iter->curr_entry += NV_RL_ENTRY_SIZE(g);
73 // Verify we haven't reached the end of the runlist 100 // Verify we haven't reached the end of the runlist
74 // rl_info.len is the num of tsg entries + total num of channel entries 101 // rl_info.len is the num of tsg entries + total num of channel entries
75 if (*pos < rl_iter->rl_info.len) { 102 if (*pos < rl_iter->rl_info.len) {
76 rl_iter->curr_tsg = next_tsg(rl_iter->curr_tsg);
77 ret = rl_iter; 103 ret = rl_iter;
78 } 104 }
79#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) 105#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)
@@ -88,57 +114,57 @@ static void runlist_file_seq_stop(struct seq_file *s, void *raw_rl_iter) {
88} 114}
89 115
90static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) { 116static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) {
91 struct entry_tsg* tsg = ((struct runlist_iter*)raw_rl_iter)->curr_tsg; 117 struct runlist_iter *rl_iter = raw_rl_iter;
92 struct runlist_chan* chan; 118 void *entry = rl_iter->curr_entry;
93 struct gk20a *g = get_live_gk20a(); 119 struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(s->file)];
94 if (!g) 120 if (entry_type(g, entry) == ENTRY_TYPE_TSG) {
95 return -EIO; 121 if (rl_iter->channels_left_in_tsg) {
96 if (tsg->entry_type != ENTRY_TYPE_TSG) { 122 printk(KERN_WARNING "[nvdebug] Found a TSG @ %px when %d channels were still expected under the previous TSG in the runlist!\n", entry, rl_iter->channels_left_in_tsg);
97 printk(KERN_WARNING "[nvdebug] Attempted to print non-TSG in tsg print logic!\n"); 123 return -EIO;
98 return -EIO; 124 }
99 } 125 rl_iter->channels_left_in_tsg = tsg_length(g, entry);
100 seq_printf(s, "+---- TSG Entry %-2d----+\n", tsg->tsgid); 126 seq_printf(s, "+---- TSG Entry %-3d---+\n", tsgid(g, entry));
101 seq_printf(s, "| Scale: %-13d|\n", tsg->timeslice_scale); 127 seq_printf(s, "| Scale: %-13d|\n", timeslice_scale(g, entry));
102 seq_printf(s, "| Timeout: %-11d|\n", tsg->timeslice_timeout); 128 seq_printf(s, "| Timeout: %-11d|\n", timeslice_timeout(g, entry));
103 seq_printf(s, "+---------------------+\n"); 129 seq_printf(s, "| Length: %-12d|\n", tsg_length(g, entry));
104 for_chan_in_tsg(chan, tsg) { 130 seq_printf(s, "+---------------------+\n");
131 } else {
132 char *indt = "";
105#ifndef DETAILED_CHANNEL_INFO 133#ifndef DETAILED_CHANNEL_INFO
106 char* loc_txt; 134 u64 instance_ptr = 0;
107 u64 instance_ptr;
108#endif 135#endif
109 if (chan->entry_type != ENTRY_TYPE_CHAN) { 136 if (rl_iter->channels_left_in_tsg) {
110 printk(KERN_WARNING "[nvdebug] Attempted to print non-channel in channel print logic!\n"); 137 indt = " ";
111 return -EIO; 138 rl_iter->channels_left_in_tsg--;
112 } 139 }
113#ifdef DETAILED_CHANNEL_INFO 140#ifdef DETAILED_CHANNEL_INFO
114 runlist_detail_seq_show_chan(s, g, chan->chid); 141 runlist_detail_seq_show_chan(s, g, chid(g, entry), indt);
115#else 142#else
116 loc_txt = target_to_text(chan->inst_target);
117 if (!loc_txt) {
118 printk(KERN_WARNING "[nvdebug] Invalid apature in channel print logic!\n");
119 return -EIO;
120 }
121 // Reconstruct pointer to channel instance block 143 // Reconstruct pointer to channel instance block
122 instance_ptr = chan->inst_ptr_hi; 144 if (g->chip_id >= NV_CHIP_ID_VOLTA) {
123 instance_ptr <<= 32; 145 instance_ptr = ((struct gv100_runlist_chan*)entry)->inst_ptr_hi;
124 instance_ptr |= chan->inst_ptr_lo << 12; 146 instance_ptr <<= 32;
125 147 }
126 seq_printf(s, " +- Channel Entry %-4d-+\n", chan->chid); 148 instance_ptr |= inst_ptr_lo(g, entry) << 12;
127 seq_printf(s, " | Runqueue Selector: %d|\n", chan->runqueue_selector); 149
128 seq_printf(s, " | Instance PTR: |\n"); 150 seq_printf(s, "%s+- Channel Entry %-4d-+\n", indt, chid(g, entry));
129 seq_printf(s, " | %#018llx |\n", instance_ptr); 151 if (g->chip_id >= NV_CHIP_ID_VOLTA)
130 seq_printf(s, " | %-20s|\n", loc_txt); 152 seq_printf(s, "%s| Runqueue Selector: %d|\n", indt,
131 seq_printf(s, " +---------------------+\n"); 153 ((struct gv100_runlist_chan*)entry)->runqueue_selector);
154 seq_printf(s, "%s| Instance PTR: |\n", indt);
155 seq_printf(s, "%s| %#018llx |\n", indt, instance_ptr);
156 seq_printf(s, "%s| %-20s|\n", indt, target_to_text(inst_target(g, entry)));
157 seq_printf(s, "%s+---------------------+\n", indt);
132#endif 158#endif
133 } 159 }
134 return 0; 160 return 0;
135} 161}
136 162
137static const struct seq_operations runlist_file_seq_ops = { 163static const struct seq_operations runlist_file_seq_ops = {
138 .start = runlist_file_seq_start, 164 .start = runlist_file_seq_start,
139 .next = runlist_file_seq_next, 165 .next = runlist_file_seq_next,
140 .stop = runlist_file_seq_stop, 166 .stop = runlist_file_seq_stop,
141 .show = runlist_file_seq_show, 167 .show = runlist_file_seq_show,
142}; 168};
143 169
144static int runlist_file_open(struct inode *inode, struct file *f) { 170static int runlist_file_open(struct inode *inode, struct file *f) {
@@ -157,6 +183,7 @@ ssize_t preempt_tsg_file_write(struct file *f, const char __user *buffer,
157 uint32_t target_tsgid; 183 uint32_t target_tsgid;
158 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec 184 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
159 int err = kstrtou32_from_user(buffer, count, 0, &target_tsgid); 185 int err = kstrtou32_from_user(buffer, count, 0, &target_tsgid);
186 struct nvdebug_state *g = &g_nvdebug_state[file2gpuidx(f)];
160 if (err) 187 if (err)
161 return err; 188 return err;
162 189
@@ -165,7 +192,7 @@ ssize_t preempt_tsg_file_write(struct file *f, const char __user *buffer,
165 return -ERANGE; 192 return -ERANGE;
166 193
167 // Execute preemption 194 // Execute preemption
168 err = preempt_tsg(target_tsgid); 195 err = preempt_tsg(g, target_tsgid);
169 if (err) 196 if (err)
170 return err; 197 return err;
171 198
@@ -181,9 +208,9 @@ ssize_t disable_channel_file_write(struct file *f, const char __user *buffer,
181 uint32_t target_channel; 208 uint32_t target_channel;
182 channel_ctrl_t chan; 209 channel_ctrl_t chan;
183 int err; 210 int err;
184 struct gk20a *g = get_live_gk20a(); 211 runlist_info_t rl_info;
185 if (!g) 212 runlist_disable_t rl_disable;
186 return -EIO; 213 struct nvdebug_state *g = &g_nvdebug_state[file2gpuidx(f)];
187 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec 214 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
188 err = kstrtou32_from_user(buffer, count, 0, &target_channel); 215 err = kstrtou32_from_user(buffer, count, 0, &target_channel);
189 if (err) 216 if (err)
@@ -195,7 +222,16 @@ ssize_t disable_channel_file_write(struct file *f, const char __user *buffer,
195 // Disable channel 222 // Disable channel
196 chan.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(target_channel)); 223 chan.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(target_channel));
197 chan.enable_clear = true; 224 chan.enable_clear = true;
225 // disable sched
226 rl_info.raw = nvdebug_readl(g, NV_PFIFO_RUNLIST);
227 rl_disable.raw = nvdebug_readl(g, NV_PFIFO_SCHED_DISABLE);
228 rl_disable.raw |= BIT(rl_info.id);
229 nvdebug_writel(g, NV_PFIFO_SCHED_DISABLE, rl_disable.raw);
230 // disable chan
198 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(target_channel), chan.raw); 231 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(target_channel), chan.raw);
232 // enable sched
233 rl_disable.raw &= ~BIT(rl_info.id);
234 nvdebug_writel(g, NV_PFIFO_SCHED_DISABLE, rl_disable.raw);
199 235
200 return count; 236 return count;
201} 237}
@@ -209,9 +245,7 @@ ssize_t enable_channel_file_write(struct file *f, const char __user *buffer,
209 uint32_t target_channel; 245 uint32_t target_channel;
210 channel_ctrl_t chan; 246 channel_ctrl_t chan;
211 int err; 247 int err;
212 struct gk20a *g = get_live_gk20a(); 248 struct nvdebug_state *g = &g_nvdebug_state[file2gpuidx(f)];
213 if (!g)
214 return -EIO;
215 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec 249 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
216 err = kstrtou32_from_user(buffer, count, 0, &target_channel); 250 err = kstrtou32_from_user(buffer, count, 0, &target_channel);
217 if (err) 251 if (err)
@@ -235,14 +269,12 @@ const struct file_operations enable_channel_file_ops = {
235ssize_t switch_to_tsg_file_write(struct file *f, const char __user *buffer, 269ssize_t switch_to_tsg_file_write(struct file *f, const char __user *buffer,
236 size_t count, loff_t *off) { 270 size_t count, loff_t *off) {
237 uint32_t target_tsgid; 271 uint32_t target_tsgid;
238 struct runlist_chan* chan; 272 struct gv100_runlist_chan* chan;
239 channel_ctrl_t chan_ctl; 273 channel_ctrl_t chan_ctl;
240 struct runlist_iter rl_iter; 274 struct runlist_iter rl_iter;
241 int err; 275 int err;
242 loff_t pos = 0; 276 loff_t pos = 0;
243 struct gk20a *g = get_live_gk20a(); 277 struct nvdebug_state *g = &g_nvdebug_state[file2gpuidx(f)];
244 if (!g)
245 return -EIO;
246 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec 278 // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec
247 err = kstrtou32_from_user(buffer, count, 0, &target_tsgid); 279 err = kstrtou32_from_user(buffer, count, 0, &target_tsgid);
248 if (err) 280 if (err)
@@ -251,32 +283,34 @@ ssize_t switch_to_tsg_file_write(struct file *f, const char __user *buffer,
251 if (target_tsgid > MAX_TSGID) 283 if (target_tsgid > MAX_TSGID)
252 return -ERANGE; 284 return -ERANGE;
253 285
254 err = get_runlist_iter(&rl_iter); 286 err = get_runlist_iter(g, 0, &rl_iter);
255 if (err) 287 if (err)
256 return err; 288 return err;
257 289
258 // Iterate through all TSGs 290 // Iterate through all TSGs
259 while (pos < rl_iter.rl_info.len) { 291 while (pos < rl_iter.rl_info.len) {
260 if (rl_iter.curr_tsg->tsgid == target_tsgid) { 292 if (tsgid(g, rl_iter.curr_entry) == target_tsgid) {
261 // Enable channels of target TSG 293 // Enable channels of target TSG
262 for_chan_in_tsg(chan, rl_iter.curr_tsg) { 294 for_chan_in_tsg(g, chan, rl_iter.curr_entry) {
263 chan_ctl.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(chan->chid)); 295 chan_ctl.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(chan->chid));
264 chan_ctl.enable_set = true; 296 chan_ctl.enable_set = true;
265 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(chan->chid), chan_ctl.raw); 297 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(chan->chid), chan_ctl.raw);
266 } 298 }
267 } else { 299 } else {
300 // XXX: Fix for bare channels. Maybe a "for_chan_until_tsg" macro?
268 // Disable all other channels 301 // Disable all other channels
269 for_chan_in_tsg(chan, rl_iter.curr_tsg) { 302 // (This is how the Jetson nvgpu driver disables TSGs)
303 for_chan_in_tsg(g, chan, rl_iter.curr_entry) {
270 chan_ctl.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(chan->chid)); 304 chan_ctl.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(chan->chid));
271 chan_ctl.enable_clear = true; 305 chan_ctl.enable_clear = true;
272 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(chan->chid), chan_ctl.raw); 306 nvdebug_writeq(g, NV_PCCSR_CHANNEL_INST(chan->chid), chan_ctl.raw);
273 } 307 }
274 } 308 }
275 pos += 1 + rl_iter.curr_tsg->tsg_length; 309 pos += 1 + tsg_length(g, rl_iter.curr_entry);
276 rl_iter.curr_tsg = next_tsg(rl_iter.curr_tsg); 310 rl_iter.curr_entry = next_tsg(g, rl_iter.curr_entry);
277 } 311 }
278 // Switch to next TSG with active channels (should be our TSG) 312 // Switch to next TSG with active channels (should be our TSG)
279 err = preempt_tsg(target_tsgid); 313 err = preempt_tsg(g, target_tsgid);
280 if (err) 314 if (err)
281 return err; 315 return err;
282 316