diff options
Diffstat (limited to 'kernel/gsp_phys_booter.c')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 247dcff..255d79e 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -4444,6 +4444,139 @@ static int gsp_phys_rm_probe(void __iomem *bar0) } /* ============================================================ + * Backend session transport API (P0 skeleton, inert) + * ============================================================ */ + +static struct gsp_phys_backend_static_config gsp_phys_backend_static; + +int gsp_phys_backend_rpc(u32 function, const void *req, u32 req_len, + void **reply, u32 *reply_len, u32 timeout_ms) +{ + struct gsp_phys_status_queue sq; + struct gsp_phys_rx_record rec; + void __iomem *bar0; + void *payload = NULL; + u32 generation; + int ret; + + if (reply) + *reply = NULL; + if (reply_len) + *reply_len = 0; + + /* + * Lock-free readiness check so a non-READY session is refused without + * taking the real-GSP lock or touching the device. The generation is + * captured before the lock and re-checked under it: a stop that bumps + * the generation between the two checks is seen below and the forward + * is refused instead of racing the release. + */ + if (gsp_phys_backend_state() != GSP_PHYS_BACKEND_READY || + !gsp_phys_gpu_claimed() || !boot_stage.rm_init_done || + boot_stage.rm_unload_submitted) { + pr_info("gsp-phys-boot: backend rpc fn%u refused: not ready (state=%d claimed=%u rm_init_done=%u unload_submitted=%u)\n", + function, gsp_phys_backend_state(), + gsp_phys_gpu_claimed(), boot_stage.rm_init_done, + boot_stage.rm_unload_submitted); + return -EAGAIN; + } + + generation = gsp_phys_backend_generation(); + bar0 = gsp_phys_gpu_bar0(); + if (!bar0) { + pr_info("gsp-phys-boot: backend rpc fn%u refused: no BAR0\n", + function); + return -ENODEV; + } + + mutex_lock(&gsp_phys_rm_lock); + if (gsp_phys_backend_state() != GSP_PHYS_BACKEND_READY || + gsp_phys_backend_generation() != generation || + !boot_stage.rm_init_done || boot_stage.rm_unload_submitted) { + u32 gen_now = gsp_phys_backend_generation(); + + mutex_unlock(&gsp_phys_rm_lock); + pr_info("gsp-phys-boot: backend rpc fn%u refused: session changed while waiting for the GSP lock (generation %u -> %u)\n", + function, generation, gen_now); + return -EAGAIN; + } + + ret = gsp_phys_queue_tx_submit(bar0, function, req, req_len); + if (ret) { + mutex_unlock(&gsp_phys_rm_lock); + pr_err("gsp-phys-boot: backend rpc fn%u submit refused: %d\n", + function, ret); + return ret; + } + + gsp_phys_status_queue_init(&sq); + memset(&rec, 0, sizeof(rec)); + ret = gsp_phys_status_wait(&sq, function, false, 0, timeout_ms, &rec); + if (ret) { + mutex_unlock(&gsp_phys_rm_lock); + pr_err("gsp-phys-boot: backend rpc fn%u no reply within %u ms (%d)\n", + function, timeout_ms, ret); + return ret; + } + + pr_info("gsp-phys-boot: backend rpc fn%u reply: payload=%u B seqNum=%u rpc.seq=%u rpc_result=0x%x private=0x%x checksum=0x%08x\n", + function, rec.payload_len, rec.seq_num, rec.rpc_sequence, + rec.rpc_result, rec.rpc_result_private, rec.checksum); + + if (rec.rpc_result != 0) { + pr_err("gsp-phys-boot: backend rpc fn%u server rpc_result=0x%x (not success)\n", + function, rec.rpc_result); + ret = -EIO; + goto out; + } + + if (reply && rec.payload_len) { + payload = kmemdup(rec.buf + GSP_PHYS_MSG_ELEMENT_PAYLOAD_OFF, + rec.payload_len, GFP_KERNEL); + if (!payload) { + ret = -ENOMEM; + goto out; + } + } + if (reply) + *reply = payload; + if (reply_len) + *reply_len = rec.payload_len; + +out: + gsp_phys_rx_record_free(&rec); + mutex_unlock(&gsp_phys_rm_lock); + return ret; +} + +int gsp_phys_backend_static_snapshot(struct gsp_phys_backend_static_config *out) +{ + u32 generation; + + if (!out) + return -EINVAL; + + if (gsp_phys_backend_state() != GSP_PHYS_BACKEND_READY) + return -EAGAIN; + + generation = gsp_phys_backend_generation(); + mutex_lock(&gsp_phys_rm_lock); + if (gsp_phys_backend_state() != GSP_PHYS_BACKEND_READY || + gsp_phys_backend_generation() != generation) { + mutex_unlock(&gsp_phys_rm_lock); + return -EAGAIN; + } + if (!gsp_phys_backend_static.valid) { + mutex_unlock(&gsp_phys_rm_lock); + pr_debug("gsp-phys-boot: backend static snapshot: cache not populated yet\n"); + return -ENODATA; + } + *out = gsp_phys_backend_static; + mutex_unlock(&gsp_phys_rm_lock); + return 0; +} + +/* ============================================================ * Host RM client ladder (R1): gsp-phys-rm-call * ============================================================ */ |
