diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 797c4b5..f7a5c7a 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -5809,6 +5809,7 @@ static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) bool verified = false; bool rb_ok = false; static u32 sem_sw_dev_log; /* r619: non-pool device-VA write budget */ + static u32 sem_sw_low_log; /* r1656: low GR release-VA write budget */ /* * Pool semaphores resolve pin -> verified cache -> targeted rm_mem @@ -5892,11 +5893,23 @@ static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) * other windows so a hot loop cannot flood dmesg. */ (va >= 0x120000000ULL && va < 0x120600000ULL && - svc.sem_sw_xg_log < 2048))) { + svc.sem_sw_xg_log < 2048) || + /* + * r1656: the direct-GL GR/GRCE release arena (0x04000000.. + * 0x0fffffff). The GR init push's SET_REPORT_SEMAPHORE + * release (e.g. va=0x4238000 pay=1) lands here, outside every + * window above, so a successful (or failed) write was + * invisible - the "decoded but never applied" class. Bounded + * so a hot release loop cannot flood dmesg. + */ + (va >= SVC_LOW_REL_VA_LO && va < SEMA_VA_LO && + sem_sw_low_log < 512))) { if (va >= 0x79240000000ULL && va < 0x79260000000ULL) svc.sem_sw_log++; else if (va >= 0x120000000ULL && va < 0x120600000ULL) svc.sem_sw_xg_log++; + else if (va >= SVC_LOW_REL_VA_LO && va < SEMA_VA_LO) + sem_sw_low_log++; else sem_sw_dev_log++; pr_info("sema-sw: h=0x%x va=0x%llx pa=0x%llx ap=%d src=%s val=0x%x rc=%d rb_ok=%d back=0x%x pool=%d\n", @@ -5909,6 +5922,16 @@ static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) svc_pool_boot_fanout(vgpu, h, va, val); svc_pool_write_all_vas(vgpu, h, va, val); svc_pool_tracker_apply(vgpu, h, va, val); + } else if (va >= 0x4000000ULL && va < 0x4300000ULL) { + /* + * r1657: direct-GL kernel-VAS semaphores. The + * general resolver can name a stale page for these + * (r1657 beef0100 rel 0x4238000 landed at the + * fallback PA while the client polls the beef0300 + * walk page). Fan the forward-only completion out + * through every published VAS translation too. + */ + svc_pool_write_all_vas(vgpu, h, va, val); } return 0; } @@ -11333,16 +11356,28 @@ static void svc_gr_bridge_fallback(struct nv_vgpu_device *vgpu) * Both still require the guest-memory path that makes any hardware * submission possible. Service-thread only, like the captures. */ -static bool svc_fwd_defer_arm(void) +static bool svc_fwd_defer_arm(u64 push_va) { if (!gsp_phys_guest_mem_enabled()) return false; if (gsp_phys_gr_forward_enabled()) { u32 ri; + /* + * r1656: the GR candidate ring survives across decode passes, + * so a candidate captured for ANOTHER launch must not withhold + * this push's release. r824 added this ownership test to the + * C56F release site only; the SET_REPORT_SEMAPHORE and + * LAUNCH_DMA sites kept the global test, and an unrelated + * lingering candidate parked a GR init release that was then + * discarded at the next pass reset (decoded, never applied). + * Only the launch's own push may defer; anything else applies + * inline. + */ for (ri = 0; ri < SVC_GR_CAND_RING; ri++) if (svc_gr_cand_ring[ri].valid && - !svc_gr_cand_ring[ri].offered) + !svc_gr_cand_ring[ri].offered && + svc_gr_cand_ring[ri].push_va == push_va) return true; } return svc_fwd_cand.valid && @@ -15202,7 +15237,20 @@ static bool svc_rel_apply_906f(struct nv_vgpu_device *vgpu, op == HOST_SEM_OP_REDUCTION); return false; } - if (!svc_sem_read(vgpu, va, &cur) && payload > cur) { + if (svc_sem_read(vgpu, va, &cur)) { + /* + * r1656: a decoded release whose target page has no + * translation yet used to be dropped here with no write, no + * pending entry and no log - unlike svc_rel_apply_reportsem() + * and svc_rel_apply_launch(), which both queue the miss. Queue + * it so svc_apply_pending() retries once a pin or the client's + * VAS walk knows the page; a reduction stays additive. + */ + svc_pending_add(va, payload, + (op == HOST_SEM_OP_REDUCTION) ? 1u : 0u); + return false; + } + if (payload > cur) { svc.pushes_pending++; cur = (op == HOST_SEM_OP_REDUCTION) ? cur + payload : payload; if (!svc_sem_write(vgpu, ch->h_object, va, cur)) { @@ -20418,7 +20466,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, * forwarding has nothing to wait * for and applies inline. */ - if (svc_fwd_defer_arm() && + if (svc_fwd_defer_arm(push_va) && svc_fwd_cand_owns_push(push_va) && !svc.op_tr_pending) { svc_opdef_drop(vgpu, ch, @@ -20595,7 +20643,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, * own it, and then it is recorded * instead of applied. */ - if (svc_fwd_defer_arm()) { + if (svc_fwd_defer_arm(push_va)) { svc_opdef_drop(vgpu, ch, entry_idx); if (svc_fwd_rel_n < SVC_FWD_REL_MAX) { @@ -22143,7 +22191,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, or.payload = st.sem_payload; or.entry_idx = entry_idx; or.dma = dma; - if (svc_fwd_defer_arm()) { + if (svc_fwd_defer_arm(push_va)) { svc_opdef_drop(vgpu, ch, entry_idx); if (svc_fwd_rel_n < SVC_FWD_REL_MAX) { |
