diff options
Diffstat (limited to 'runlist.c')
| -rw-r--r-- | runlist.c | 69 |
1 files changed, 67 insertions, 2 deletions
| @@ -14,6 +14,52 @@ | |||
| 14 | // be enabled to print the runlist on the TX2. | 14 | // be enabled to print the runlist on the TX2. |
| 15 | //#define FALLBACK_TO_PRAMIN | 15 | //#define FALLBACK_TO_PRAMIN |
| 16 | 16 | ||
| 17 | /* Get RunList RAM (RLRAM) offset for a runlist from the device topology | ||
| 18 | @param rl_id Which runlist to obtain [numbered in order of appearance in | ||
| 19 | the device topology (PTOP) registers] | ||
| 20 | @param rl_ram_off Location at which to store runlist private register | ||
| 21 | interface base address (PRI base); an offset into the BAR0 | ||
| 22 | register range. | ||
| 23 | @return 0 or -errno on error | ||
| 24 | */ | ||
| 25 | int get_runlist_ram(struct nvdebug_state *g, int rl_id, uint32_t *rl_ram_off) { | ||
| 26 | int i; | ||
| 27 | int curr_rl_id = 0; | ||
| 28 | int ptop_size = NV_PTOP_DEVICE_INFO__SIZE_1_GA100(g); | ||
| 29 | // Each PTOP entry is composed of 1--3 subrows, and the fields available | ||
| 30 | // on each row vary. The runlist RAM location is only available on row 3 | ||
| 31 | int ptop_entry_subrow = 0; | ||
| 32 | ptop_device_info_ga100_t ptop_entry; | ||
| 33 | // Iterate through all PTOP entries | ||
| 34 | for (i = 0; i < ptop_size; i++) { | ||
| 35 | if ((ptop_entry.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_GA100(i))) == -1) | ||
| 36 | return -EIO; | ||
| 37 | // Skip empty entries | ||
| 38 | if (!ptop_entry.raw) | ||
| 39 | continue; | ||
| 40 | // If on subrow 3 (zero-base-index 2), runlist info is available | ||
| 41 | // Multiple engines may be associated with a single runlist, so | ||
| 42 | // multiple PTOP entries may refer to the same runlist. Only match when | ||
| 43 | // on the 0th-associated entry. | ||
| 44 | if (ptop_entry_subrow == 2 && ptop_entry.rleng_id == 0) { | ||
| 45 | // If this is the requested runlist, return it | ||
| 46 | if (curr_rl_id == rl_id) { | ||
| 47 | *rl_ram_off = (uint32_t)ptop_entry.runlist_pri_base << 10; | ||
| 48 | return 0; | ||
| 49 | } | ||
| 50 | // Otherwise, update our accounting of what the next runlist ID is | ||
| 51 | curr_rl_id++; | ||
| 52 | } | ||
| 53 | // Track if the next row is a subrow of the current entry | ||
| 54 | if (ptop_entry.has_next_entry) | ||
| 55 | ptop_entry_subrow += 1; | ||
| 56 | else | ||
| 57 | ptop_entry_subrow = 0; | ||
| 58 | } | ||
| 59 | // Search failed; requested index does not exist | ||
| 60 | return -EINVAL; | ||
| 61 | } | ||
| 62 | |||
| 17 | /* Get runlist head and info (incl. length) | 63 | /* Get runlist head and info (incl. length) |
| 18 | @param rl_id Which runlist to obtain? | 64 | @param rl_id Which runlist to obtain? |
| 19 | @param rl_iter Location at which to store output | 65 | @param rl_iter Location at which to store output |
| @@ -39,7 +85,7 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 39 | runlist_target = rl.target; | 85 | runlist_target = rl.target; |
| 40 | runlist_len = rl.len; | 86 | runlist_len = rl.len; |
| 41 | printk(KERN_INFO "[nvdebug] Runlist %d for %x: %d entries @ %llx in %s (config raw: %#018llx)\n", | 87 | printk(KERN_INFO "[nvdebug] Runlist %d for %x: %d entries @ %llx in %s (config raw: %#018llx)\n", |
| 42 | rl_id, g->chip_id, rl.len, runlist_iova, target_to_text(rl.target), rl.raw); | 88 | rl_id, g->chip_id, rl.len, runlist_iova, target_to_text(rl.target), rl.raw); |
| 43 | } else if (g->chip_id < NV_CHIP_ID_AMPERE) { | 89 | } else if (g->chip_id < NV_CHIP_ID_AMPERE) { |
| 44 | runlist_base_tu102_t base; | 90 | runlist_base_tu102_t base; |
| 45 | runlist_submit_tu102_t submit; | 91 | runlist_submit_tu102_t submit; |
| @@ -51,7 +97,26 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 51 | runlist_target = base.target; | 97 | runlist_target = base.target; |
| 52 | runlist_len = submit.len; | 98 | runlist_len = submit.len; |
| 53 | printk(KERN_INFO "[nvdebug] Runlist %d for %x: %d entries @ %llx in %s (config raw: %#018llx %#018llx)\n", | 99 | printk(KERN_INFO "[nvdebug] Runlist %d for %x: %d entries @ %llx in %s (config raw: %#018llx %#018llx)\n", |
| 54 | rl_id, g->chip_id, submit.len, runlist_iova, target_to_text(runlist_target), base.raw, submit.raw); | 100 | rl_id, g->chip_id, submit.len, runlist_iova, target_to_text(runlist_target), base.raw, submit.raw); |
| 101 | } else { | ||
| 102 | runlist_base_tu102_t base; | ||
| 103 | runlist_submit_tu102_t submit; | ||
| 104 | uint32_t runlist_pri_base; | ||
| 105 | // Runlist configurations are stored in per-runlist regions on Ampere+ | ||
| 106 | if ((err = get_runlist_ram(g, rl_id, &runlist_pri_base)) < 0) | ||
| 107 | return err; | ||
| 108 | // The runlist configuration region (RLRAM) contains Turing-like BASE | ||
| 109 | // and SUBMIT registers at static offsets | ||
| 110 | if ((base.raw = nvdebug_readq(g, runlist_pri_base + NV_RUNLIST_BASE_GA100)) == -1) | ||
| 111 | return -EIO; | ||
| 112 | if ((submit.raw = nvdebug_readq(g, runlist_pri_base + NV_RUNLIST_SUBMIT_GA100)) == -1) | ||
| 113 | return -EIO; | ||
| 114 | runlist_iova = ((uint64_t)base.ptr) << 12; | ||
| 115 | runlist_target = base.target; | ||
| 116 | runlist_len = submit.len; | ||
| 117 | printk(KERN_INFO "[nvdebug] Runlist %d for %x: %d entries @ %llx in %s (config raw: %#018llx %#018llx)\n", | ||
| 118 | rl_id, g->chip_id, submit.len, runlist_iova, target_to_text(runlist_target), base.raw, submit.raw); | ||
| 119 | rl_iter->runlist_pri_base = runlist_pri_base; | ||
| 55 | } | 120 | } |
| 56 | // Return early on an empty runlist | 121 | // Return early on an empty runlist |
| 57 | if (!runlist_len) | 122 | if (!runlist_len) |
