diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-01 21:59:42 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-01 21:59:42 -0400 |
| commit | ad6804d6af9b1a49604697ec775181d6e8f96fa1 (patch) | |
| tree | bc49409a6cd575ba512787432f946093b7a1a586 /kernel/gsp_phys_gpu.c | |
| parent | c50eacb25fdc43826aa631aa1fc20ef66774882f (diff) | |
| download | open-iov-ad6804d6af9b1a49604697ec775181d6e8f96fa1.tar.gz open-iov-ad6804d6af9b1a49604697ec775181d6e8f96fa1.zip | |
gsp-phys: backend session API skeleton (P0, inert)
Diffstat (limited to 'kernel/gsp_phys_gpu.c')
| -rw-r--r-- | kernel/gsp_phys_gpu.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c index 88d13f2..22cdc33 100644 --- a/kernel/gsp_phys_gpu.c +++ b/kernel/gsp_phys_gpu.c @@ -49,6 +49,7 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/mutex.h> #include <linux/pci.h> #include <linux/pm_runtime.h> #include <linux/delay.h> @@ -1001,3 +1002,129 @@ void gsp_phys_gpu_release(void) gsp_phys_power_unlock(); } + +/* + * Backend session state (P0 skeleton, inert until a caller wires it). One + * physical GPU, one live claim, refcounted between the module-owned + * load-time claim and the guest-facing mdev owner. gsp_phys_session_lock is + * the outermost backend lock: it is held for state/refcount/owner changes + * only and dropped before gsp_phys_gpu_claim()/_release(), which take + * gsp_phys_rm_lock inside. The generation counter is bumped when the session + * leaves READY so a forward that captured the previous value can re-check it + * under the rm lock and refuse instead of racing the release. + */ +static DEFINE_MUTEX(gsp_phys_session_lock); + +static struct gsp_phys_backend_session { + enum gsp_phys_backend_state state; + u32 refcount; + u32 generation; + bool module_owned; +} backend = { + .state = GSP_PHYS_BACKEND_OFF, +}; + +int gsp_phys_backend_state(void) +{ + return READ_ONCE(backend.state); +} + +u32 gsp_phys_backend_generation(void) +{ + return READ_ONCE(backend.generation); +} + +int gsp_phys_backend_start(void) +{ + bool was_claimed; + int ret; + + mutex_lock(&gsp_phys_session_lock); + if (backend.state != GSP_PHYS_BACKEND_OFF) { + backend.refcount++; + pr_info("gsp-phys: backend start: session already up (state=%d, refcount=%u)\n", + backend.state, backend.refcount); + mutex_unlock(&gsp_phys_session_lock); + return 0; + } + + /* + * A live claim can only pre-exist from the load-time module-owned + * path; join it without claiming again and keep the module as the + * owner so a later stop() drops only the reference and leaves the + * release to rmmod. + */ + was_claimed = gsp_phys_gpu_claimed(); + backend.refcount = 1; + backend.module_owned = was_claimed; + WRITE_ONCE(backend.state, GSP_PHYS_BACKEND_CLAIMING); + mutex_unlock(&gsp_phys_session_lock); + + if (!was_claimed) { + pr_info("gsp-phys: backend start: claiming the physical GPU\n"); + ret = gsp_phys_gpu_claim(); + if (ret) { + mutex_lock(&gsp_phys_session_lock); + backend.refcount = 0; + backend.module_owned = false; + WRITE_ONCE(backend.state, GSP_PHYS_BACKEND_OFF); + mutex_unlock(&gsp_phys_session_lock); + pr_err("gsp-phys: backend start: claim failed: %d (backend OFF)\n", + ret); + return ret; + } + } + + /* + * gsp_phys_gpu_claim() runs the stage-3d boot inline when the boot + * parameters are set, so READY here means the session is owned and + * live; gsp_phys_backend_rpc() additionally gates on init-done. + */ + mutex_lock(&gsp_phys_session_lock); + WRITE_ONCE(backend.state, GSP_PHYS_BACKEND_READY); + pr_info("gsp-phys: backend start: READY (module-owned=%u)\n", + backend.module_owned); + mutex_unlock(&gsp_phys_session_lock); + return 0; +} + +void gsp_phys_backend_stop(void) +{ + u32 generation; + + mutex_lock(&gsp_phys_session_lock); + if (backend.state == GSP_PHYS_BACKEND_OFF) { + mutex_unlock(&gsp_phys_session_lock); + pr_info("gsp-phys: backend stop: already OFF\n"); + return; + } + if (backend.refcount) + backend.refcount--; + if (backend.refcount) { + pr_info("gsp-phys: backend stop: refcount=%u, session stays up\n", + backend.refcount); + mutex_unlock(&gsp_phys_session_lock); + return; + } + if (backend.module_owned || + backend.state != GSP_PHYS_BACKEND_READY) { + pr_info("gsp-phys: backend stop: state=%d owner=%s, no release\n", + backend.state, + backend.module_owned ? "module" : "mdev"); + mutex_unlock(&gsp_phys_session_lock); + return; + } + + WRITE_ONCE(backend.state, GSP_PHYS_BACKEND_STOPPING); + generation = ++backend.generation; + mutex_unlock(&gsp_phys_session_lock); + pr_info("gsp-phys: backend stop: STOPPING (generation=%u)\n", generation); + + gsp_phys_gpu_release(); + + mutex_lock(&gsp_phys_session_lock); + backend.module_owned = false; + WRITE_ONCE(backend.state, GSP_PHYS_BACKEND_OFF); + mutex_unlock(&gsp_phys_session_lock); + pr_info("gsp-phys: backend stop: OFF\n"); +} |
