#include // For seq_* functions and types #include "nvdebug.h" #define RUNLIST_PROCFS_NAME "runlist" static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) { static struct runlist_iter rl_iter; // *pos == 0 for first call after read of file if (*pos == 0) { int err = get_runlist_iter(&rl_iter); if (err) return NULL; return &rl_iter; } // When called with *pos != 0, we already traversed the runlist return NULL; } static void* runlist_file_seq_next(struct seq_file *s, void *raw_rl_iter, loff_t *pos) { struct runlist_iter* rl_iter = raw_rl_iter; // Advance by one TSG + channels under last TSG *pos += 1 + rl_iter->curr_tsg->tsg_length; // Verify we haven't reached the end of the runlist // rl_info.len is the num of tsg entries + total num of channel entries if (*pos < rl_iter->rl_info.len) { rl_iter->curr_tsg = next_tsg(rl_iter->curr_tsg); return rl_iter; } return NULL; } static void runlist_file_seq_stop(struct seq_file *s, void *raw_rl_iter) { // No cleanup needed } static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) { struct entry_tsg* tsg = ((struct runlist_iter*)raw_rl_iter)->curr_tsg; struct runlist_chan* chan; if (tsg->entry_type != ENTRY_TYPE_TSG) { printk(KERN_WARNING "[nvdebug] Attempted to print non-TSG in nvdebug_print_tsg()!\n"); return -EIO; } seq_printf(s, "+---- TSG Entry %-2d----+\n", tsg->tsgid); seq_printf(s, "| Scale: %-13d|\n", tsg->timeslice_scale); seq_printf(s, "| Timeout: %-11d|\n", tsg->timeslice_timeout); seq_printf(s, "+---------------------+\n"); for_chan_in_tsg(chan, tsg) { char* loc_txt; u64 instance_ptr; if (chan->entry_type != ENTRY_TYPE_CHAN) { printk(KERN_WARNING "[nvdebug] Attempted to print non-channel in nvdebug_print_channel()!\n"); return -EIO; } switch (chan->inst_target) { case TARGET_VID_MEM: loc_txt = "VID_MEM"; break; case TARGET_SYS_MEM_COHERENT: loc_txt = "SYS_MEM_COHERENT"; break; case TARGET_SYS_MEM_NONCOHERENT: loc_txt = "SYS_MEM_NONCOHERENT"; break; default: printk(KERN_WARNING "[nvdebug] Invalid aperture in runlist channel!\n"); return -EIO; } // Reconstruct pointer to channel instance block instance_ptr = chan->inst_ptr_hi; instance_ptr <<= 32; instance_ptr |= chan->inst_ptr_lo << 12; seq_printf(s, " +- Channel Entry %-4d-+\n", chan->chid); seq_printf(s, " | Runqueue Selector: %d|\n", chan->runqueue_selector); seq_printf(s, " | Instance PTR: |\n"); seq_printf(s, " | %#018llx |\n", instance_ptr); seq_printf(s, " | %-20s|\n", loc_txt); seq_printf(s, " +---------------------+\n"); } return 0; } static const struct seq_operations runlist_file_seq_ops = { .start = runlist_file_seq_start, .next = runlist_file_seq_next, .stop = runlist_file_seq_stop, .show = runlist_file_seq_show, }; static int runlist_file_open(struct inode *inode, struct file *f) { return seq_open(f, &runlist_file_seq_ops); } const struct file_operations runlist_file_ops = { .open = runlist_file_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, };