Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions drivers/gpu/drm/asahi/fw/workqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub(crate) mod raw {
pub(crate) unk_94: u32,
pub(crate) pending: AtomicU32,
pub(crate) unk_9c: u32,
pub(crate) gpu_context: GpuPointer<'a, super::GpuContextData>,
pub(crate) gpu_context: GpuWeakPointer<super::GpuContextData>,
pub(crate) unk_a8: U64,
#[ver(V >= V13_2 && G < G14X)]
pub(crate) unk_b0: u32,
Expand All @@ -171,14 +171,17 @@ impl GpuStruct for GpuContextData {
type Raw<'a> = raw::GpuContextData;
}

/// The firmware structures of a work queue.
///
/// The raw structure points to the queue's GPU context weakly. The `GpuContext` keeps these
/// structures until it has been invalidated, and only then frees its own data.
#[versions(AGX)]
#[derive(Debug)]
pub(crate) struct QueueInfo {
pub(crate) state: GpuObject<RingState>,
pub(crate) ring: GpuArray<u64>,
pub(crate) gpu_buf: GpuArray<u8>,
pub(crate) notifier_list: Arc<GpuObject<event::NotifierList>>,
pub(crate) gpu_context: Arc<crate::workqueue::GpuContext>,
}

#[versions(AGX)]
Expand Down
14 changes: 8 additions & 6 deletions drivers/gpu/drm/asahi/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,8 @@ pub(crate) struct GpuManager {
stats: Arc<stats::StatsSnapshot>,
buffer_mgr: buffer::BufferManager::ver,
ids: SequenceIDs,
#[allow(clippy::vec_box)]
#[pin]
garbage_contexts: Mutex<KVec<KBox<fw::types::GpuObject<fw::workqueue::GpuContextData>>>>,
garbage_contexts: Mutex<KVec<workqueue::RetiredContext>>,
}

/// Operations the DRM driver performs on a GPU, independent of its firmware interface.
Expand Down Expand Up @@ -401,8 +400,8 @@ pub(crate) trait GpuManager: Send + Sync {
fn get_cfg(&self) -> &'static hw::HwConfig;
/// Get the dynamic GPU configuration for this SoC.
fn get_dyncfg(&self) -> &hw::DynConfig;
/// Register an unused context as garbage
fn free_context(&self, data: KBox<fw::types::GpuObject<fw::workqueue::GpuContextData>>);
/// Register an unused context, with the objects it retains, for invalidation.
fn free_context(&self, ctx: workqueue::RetiredContext);
}

/// Private generic trait for functions that don't need to escape this module.
Expand Down Expand Up @@ -1456,7 +1455,7 @@ impl GpuManager for GpuManager::ver {
core::mem::swap(&mut *self.garbage_contexts.lock(), &mut garbage_ctx);

for ctx in garbage_ctx {
if self.invalidate_context(&ctx).is_err() {
if self.invalidate_context(&ctx.data).is_err() {
dev_err!(
self.dev.as_ref(),
"GpuContext: Failed to invalidate GPU context!\n"
Expand All @@ -1465,6 +1464,9 @@ impl GpuManager for GpuManager::ver {
panic!("GPU firmware timed out");
}
}
// The firmware no longer knows the context's queues, so their structures may go now,
// ahead of the context data they point to.
core::mem::drop(ctx.retained);
}

let mut guard = self.alloc.lock();
Expand Down Expand Up @@ -1733,7 +1735,7 @@ impl GpuManager for GpuManager::ver {
&self.dyncfg
}

fn free_context(&self, ctx: KBox<fw::types::GpuObject<fw::workqueue::GpuContextData>>) {
fn free_context(&self, ctx: workqueue::RetiredContext) {
let mut garbage = self.garbage_contexts.lock();

if garbage.push(ctx, GFP_KERNEL).is_err() {
Expand Down
15 changes: 10 additions & 5 deletions drivers/gpu/drm/asahi/queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,15 @@ impl Queue::ver {

let buffer = buffer::Buffer::ver::new(gpu, alloc, ualloc.clone(), ualloc_priv, mgr)?;

let gpu_context = Arc::new(
workqueue::GpuContext::new(dev.clone(), alloc, buffer.any_ref())?,
GFP_KERNEL,
)?;
// Every command of this queue points the firmware at the notifier, and the notifier links
// into the notifier list of the work queues. Keep it as long as they are kept, until the
// context is invalidated, instead of freeing it with the last command.
gpu_context.retain(KBox::new(notifier.clone(), GFP_KERNEL)?)?;

let mut ret = Queue::ver {
dev: dev.clone(),
_sched: sched,
Expand All @@ -538,11 +547,7 @@ impl Queue::ver {
inner: QueueInner::ver {
dev: dev.clone(),
ualloc,
gpu_context: Arc::new(
workqueue::GpuContext::new(dev.clone(), alloc, buffer.any_ref())?,
GFP_KERNEL,
)?,

gpu_context,
buffer,
notifier_list: Arc::new(notifier_list, GFP_KERNEL)?,
notifier,
Expand Down
Loading