Repository navigation
G15: fix stamp wrap and VM slot exhaustion #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-only OR MIT | ||
|
|
||
| //! G15 hardware and firmware-ABI constants (layout values are shared by several modules; change | ||
|
|
@@ -518,8 +518,6 @@ | |
| pub(crate) const AHEAD_RECORDS: u32 = 64; | ||
| /// Policy bound on logical queues reported in QUEUE_LIMITS (not a firmware limit). | ||
| pub(crate) const MAX_QUEUES: u32 = 58; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing |
||
| /// TTBAT user slots: user VMs hold one each for their lifetime (ASIDs 1..63). | ||
| pub(crate) const MAX_VMS: u32 = 63; | ||
| } | ||
|
|
||
| /// Firmware channels, doorbells, seeds and identifiers. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-only OR MIT | ||
|
|
||
| //! Jobs: one per SUBMIT, scheduled by a per-queue DRM scheduler and executed by the engine. | ||
|
|
@@ -22,29 +22,35 @@ | |
| //! exactly once with [`Job::complete`] (later calls are ignored), through [`Completions`] | ||
| //! collected under the device lock and [`complete_all`] after it is dropped. A job whose storage | ||
| //! the firmware may still reference stays in `Engine::retained` (failed jobs until reboot): its | ||
| //! [`mmu::VmJobGuard`] keeps the VM's mappings and its VM state keeps the VM's TTBAT slot until | ||
| //! [`mmu::VmJobGuard`] keeps the VM's mappings and its binding keeps the VM's TTBAT slot until | ||
| //! the last `Arc<Job>` drops. | ||
|
|
||
| use core::sync::atomic::{AtomicBool, Ordering}; | ||
| use core::sync::atomic::{AtomicBool, AtomicU32, Ordering}; | ||
| use kernel::{ | ||
| bindings, c_str, device, | ||
| dma_fence::{Fence, RawDmaFence}, | ||
| drm::sched, | ||
| new_mutex, | ||
| prelude::*, | ||
| sync::Arc, | ||
| sync::{Arc, Mutex}, | ||
| }; | ||
|
|
||
| use super::{command::Command, fence::JobFence, hw, queue::QueueState, vm::VmState, Shared}; | ||
| use crate::mmu; | ||
|
|
||
| /// A job as the engine sees it. | ||
| #[pin_data] | ||
| pub(crate) struct Job { | ||
| /// Submission ID (debugging). | ||
| pub(crate) id: u64, | ||
| /// The submitting queue (priority, service turn, horizon history). | ||
| pub(crate) queue: Arc<QueueState>, | ||
| /// The job's VM (TTBAT slot, status). | ||
| /// The job's VM and status. | ||
| pub(crate) vm: Arc<VmState>, | ||
| /// Hardware context, assigned immediately before the engine publishes the job. | ||
| context: AtomicU32, | ||
| #[pin] | ||
| binding: Mutex<Option<mmu::VmBind>>, | ||
| /// Validated commands, in submission order (at most 64). | ||
| pub(crate) commands: KVec<Command>, | ||
| /// The job's hardware fence. | ||
|
|
@@ -73,21 +79,43 @@ | |
| guard: mmu::VmJobGuard, | ||
| ) -> Result<Arc<Self>> { | ||
| let progress = super::engine::Progress::new(commands.len()); | ||
| Ok(Arc::new( | ||
| Self { | ||
| Arc::pin_init( | ||
| pin_init!(Self { | ||
| id, | ||
| queue, | ||
| vm, | ||
| context: AtomicU32::new(0), | ||
| binding <- new_mutex!(None, "g15::Job::binding"), | ||
| commands, | ||
| fence, | ||
| progress, | ||
| _timestamps: timestamps, | ||
| _guard: guard, | ||
| accepted: AtomicBool::new(false), | ||
| started: AtomicBool::new(false), | ||
| }, | ||
| }), | ||
| GFP_KERNEL, | ||
| )?) | ||
| ) | ||
| } | ||
|
|
||
| pub(crate) fn slot(&self) -> u32 { | ||
| self.context.load(Ordering::Relaxed) | ||
| } | ||
|
|
||
| /// Called under the device lock immediately before publication. | ||
| pub(crate) fn bind(&self) -> Result { | ||
| let mut slot = self.binding.lock(); | ||
| if slot.is_none() { | ||
| let binding = self.vm.try_bind()?; | ||
| self.context.store(binding.slot(), Ordering::Relaxed); | ||
| *slot = Some(binding); | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
| /// All commands retired successfully, or nothing of the job was published. | ||
| pub(crate) fn release_binding(&self) { | ||
| drop(self.binding.lock().take()); | ||
| } | ||
|
|
||
| /// Completes the job: latches the VM status on failure, then signals the fence (after every | ||
|
|
@@ -120,6 +148,9 @@ | |
| self.vm.status.record(error); | ||
| } | ||
| } | ||
| if result.is_ok() || !engine { | ||
| self.release_binding(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
| self.fence.signal(result); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
rustfmt --checkwants this arm in braces.