Commit graph

1,483,277 commits

Author SHA1 Message Date
Tvrtko Ursulin
5d7ffdc7f8 drm/amdgpu: Convert SDMA instance and index to direct lookup
Instead of searching for the matching SDMA instance inside many of the
SDMA ring vfuncs lets just use the instance number already stored in the
ring and replace the function calls and array walks with direct lookups.

As these helpers are used only from SDMA vfuncs we can remove safely
remove the "is this a SDMA ring" checks as well.

We could add an assert that ring->type queried is AMDGPU_RING_TYPE_SDMA
but as currently there are no debug build only assert macros in this
driver for now I opted not to so the helper can stay a trivial static
inline without polluting the callers with out of line logging.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Tvrtko Ursulin
ce23f00eb1 drm/amdgpu: Add amdgpu_sdma_types.h header
There is an include loop between amdgpu.h and amdgpu_sdma.h which
prevents adding any interesting static inline helpers to the latter.

Break it by moving the type definitions to a new amdgpu_sdma_types.h
header.

This is required so static inline helpers which need to dereference
struct amdgpu_device can be added to amdgpu_sdma.h.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Hari Mishal
f35aa5c77f drm/amd/pm: bound SCLK FCW range entries to the table size
atomctrl_get_smc_sclk_range_table() copies ucSclkEntryNum entries from
the VBIOS SMU_Info table into pp_atom_ctrl_sclk_range_table. Both the
source (asSclkFcwRangeEntry[]) and destination (table->entry[]) arrays
are fixed at MAX_SCLK_RANGE (8) entries, but ucSclkEntryNum is an
unchecked u8 read straight from the VBIOS, so it can be up to 255. The
destination is stack-allocated in both callers
(polaris10_get_sclk_range_table(), vegam_get_sclk_range_table()), so a
count above 8 overflows a stack buffer, not just a heap read.

Reject counts above MAX_SCLK_RANGE rather than clamping to it. Only
one version of this VBIOS struct (ATOM_SMU_INFO_V2_1) has ever
existed, so a count above 8 corresponds to no legitimate table format
and means either a corrupted or a tampered VBIOS.

Fixes: a23eefa2f4 ("drm/amd/powerplay: enable dpm for baffin.")
Assisted-by: gkh_clanker_t1000
Signed-off-by: Hari Mishal <harimishal1@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Mukul Joshi
b2adbdf861 drm/amdkfd: set CP_HQD_PQ_CONTROL.SCOPE to SYSTEM for GFX 12.1
On GFX 12.1, ring buffers may be mapped with a non-coherently
cached memory type. In that case the queue fetch can observe stale
packets, since the packet producers (CPU or other GPUs) do not keep the
device-side cache coherent.

Set CP_HQD_PQ_CONTROL.SCOPE=3 (SYSTEM) so the queue fetches use
system scope and pick up the latest packets. Apply this to compute queue
MQDs and to MES-managed queues.

Without this, the queue can consume stale packets for long periods,
causing severe slowdowns and, in the worst case, application hangs.

Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Signed-off-by: Joseph Greathouse <joseph.greathouse@amd.com>
Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Omokefe Emmanuel Onanaroghene
5119c21145 drm/amd/display: fix kernel-doc warnings for amdgpu_display_manager
scripts/kernel-doc reports missing and excess member descriptions
for struct amdgpu_display_manager:

  struct member 'power_module' not described
  struct member 'hdmi_frl_status_polling_wq' not described
  struct member 'hdmi_frl_status_polling_delay_ms' not described
  struct member 'boot_time_crc_info' not described
  Excess struct member 'dm_boot_time_crc_info' description

Add @power_module to the main struct doc, document
hdmi_frl_status_polling_wq/work/delay_ms with separate inline
comments, and rename @dm_boot_time_crc_info to @boot_time_crc_info
to match the actual member name.

Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Ruslan Vagner
acf47ef456 drm/amd: fix comment typos in amdgpu and radeon
Fix the spelling in comments. No functional change.

Signed-off-by: Ruslan Vagner <rusya92266@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Dmitriy Chumachenko
c7071767a5 drm/amdgpu: check ras and obj before dereference
nbio_v7_9_handle_ras_controller_intr_no_bifring() dereferences ras and obj
without checking either for NULL. Both amdgpu_ras_get_context() and
amdgpu_ras_find_obj() can return NULL, e.g. during the window between
adev->nbio.ras being set (early in amdgpu_ras_init(), by design, to
enable the fatal-error interrupt as soon as possible) and the PCIE_BIF
ras object actually being created in RAS late_init. Any interrupt in that
window crashes in hard-IRQ context.

This is analogous to commit d190b459b2 ("drm/amdgpu: the warning
dereferencing obj for nbio_v7_4"), which fixed the same issue in the
nbio_v7_4 handler.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: 7692e1ee24 ("drm/amdgpu: add RAS fatal error handler for NBIO v7.9")
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Signed-off-by: Dmitriy Chumachenko <Dmitry.Chumachenko@cyberprotect.ru>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Timur Kristóf
e42eb28168 drm/amdgpu/sdma: Use common SDMA legacy queue reset on SDMA v4.4.2
Now, sdma_v4_4_2_reset_queue() does basically the same
as amdgpu_sdma_reset_queue_legacy() so let's use that.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Tvrtko Ursulin
6959043d96 drm/amdgpu: Add SDMA ring init helper
Consolidate one part of the SDMA ring initialization with a new
amdgpu_sdma_ring_init() helper.

Only code which is completely IP version agnostic is moved to the helper.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Vitaly Prosyak
a2a2774535 drm/amdgpu: reserve root PD fence slots for userq eviction-fence rearm
Root cause:
- In userq restore/rearm, root PD was locked with amdgpu_vm_lock_pd(vm, &exec, 1).
- Later in the same drm_exec context, amdgpu_evf_mgr_rearm() attaches
  BOOKKEEP eviction fences to all locked BOs.
- In this flow, root PD validation/update can also consume move-fence slots,
  so reserving only +1 at PD lock time is not sufficient under stress.

Fix:
- Reserve caller-side slots at the actual source by switching to:
  amdgpu_vm_lock_pd(vm, &exec, TTM_NUM_MOVE_FENCES + 1)

This keeps reservation policy in callers, consistent with Christian Konig
feedback and with amdgpu_gem_object_open() where callers reserve
TTM_NUM_MOVE_FENCES + 1 before attaching eviction fences.

Credit:
- Christian Konig: confirmed fence-slot reservation belongs to callers and
  asked to investigate why +1 was still not enough.
- Prike Liang: clarified the initial variant was workaround-only and
  developed that initial version independently.

Cc: Prike Liang <prike.liang@amd.com>
Cc: Sunil Khatri <sunil.khatri@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Vitaly Prosyak
5e6b21bce9 drm/amdgpu: reserve eviction-fence slot at WPTR caller
Root cause analysis showed that the previous workaround was fixing the
symptom in the wrong layer.

Problem:
  kernel BUG at drivers/dma-buf/dma-resv.c:319!
  BUG_ON(fobj->num_fences >= fobj->max_fences)
  Workqueue: events amdgpu_userq_restore_worker

- amdgpu_evf_mgr_attach_fence() had been temporarily taught to reserve/add
  fence bookkeeping internally as a workaround.
- This hid the real contract violation and made reservation policy implicit
  inside a helper.

Review clarification:
- The helper-side dma_resv_add_fence-related workaround was only an intended
  proposal sent for review discussion, not the final direction.
- Final fix keeps fence-slot reservation explicit in callers and leaves the
  helper free of policy decisions.

Findings from investigation:
- drm_exec_prepare_obj() both locks and reserves fence slots.
- drm_exec_lock_obj() only locks and does not reserve slots.
- Existing attach_fence callers in the GEM/userq restore flows already reserve
  TTM_NUM_MOVE_FENCES + 1 before adding the bookkeeping eviction fence.
- The WPTR mapping path in mes_userq_create_wptr_mapping() used
  drm_exec_lock_obj() and then called amdgpu_evf_mgr_attach_fence(), so this
  specific path could add a fence without pre-reserved space.

Fix:
- Switch the WPTR mapping path to drm_exec_prepare_obj(...,
  TTM_NUM_MOVE_FENCES + 1), restoring the caller-side reservation contract.
- Remove the helper-side reservation workaround from
  amdgpu_evf_mgr_attach_fence().

Why this is the right layer:
- Reservation policy stays explicit at call sites that define how many fences
  may be added in that execution context.
- The helper only performs validate + add_fence when called with a properly
  prepared reservation object, matching the existing drm_exec model.

Fixes: 7264bc10c7 (drm/amdgpu: dont pin wptr bo instead use eviction fence)
Cc: Sunil Khatri <sunil.khatri@amd.com>
Cc: Prike Liang <prike.liang@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Reviewed-by: Prike Liang <prike.liang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Mario Limonciello
1b7f848c1d drm/radeon: restore eDP panel power sequencer on Apple DCE3.2 iMacs
The Apple iMac10,1 and iMac11,2 (RV730/DCE3.2) drive their internal eDP
panel through an LVTMA power sequencer whose enable bit (PWRSEQ_EN in
LVTMA_PWRSEQ_CNTL) is programmed exactly once, by EFI at cold boot.
Apple's minimal ATOM tables never touch it afterwards, so any GPU
re-initialisation - S3 resume or a GPU-lockup reset - clears PWRSEQ_EN
and the panel comes back dark while the rest of the GPU resumes fine.

The driver never programs this register itself; on every other radeon
board the platform firmware maintains it across a re-POST, which is why
this only bites the Apple machines. Re-assert PWRSEQ_EN in the eDP
DPMS-on path when it is found cleared; the hardware then runs the
DIGON->DE->VARY_BL->BLON power-on sequence on its own. Both failure
paths pass through here, as radeon_gpu_reset() restores the modeset
state via radeon_resume_kms(), so a single site covers resume and reset.

The write is gated to Apple parts and to exactly DCE3.2 (ASIC_IS_DCE32
is >= RV730, so DCE4+ must be excluded - Apple also shipped DCE5, e.g.
the 2011 MacBook Pro, where the register lives at a different offset).
It is skipped when the sequencer is already enabled, so lit panels,
DCE4+ boards and non-Apple boards are untouched. DCE3.2 places the
register 0x18 above the documented R600 offset.

Only iMac11,2 is verified on hardware; iMac10,1 shares the same RV730
design and Apple EFI behaviour.

Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/5719
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260914022002.2005150-1-mario.limonciello@amd.com
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Mukul Joshi
9355ae92f2 drm/amdgpu: Fix missed connection cleanup on HELLO reset for UALink
When a HELLO arrived on an already ESTABLISHED connection,
amdgpu_ualink_process_hello_msg() set the state to PENDING before
calling amdgpu_ualink_handle_connection_reset(). That function only
runs the imp/exp XA cleanup when it observes the state as ESTABLISHED,
so the premature change skipped the cleanup and left stale NPA
mappings and pinned BOs from the previous connection.

Leave the state as ESTABLISHED and let
amdgpu_ualink_handle_connection_reset() perform the transition, so the
cleanup runs.

Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Reviewed-by : Philip Yang <philip.yang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Mike Lothian
062ff15e30 drm/amdgpu: hold a runtime PM reference for P2P dma-buf attachments
amdgpu_dma_buf_map() adds VRAM to the allowed domains for a peer2peer
attachment.  GTT is only a fallback placement when VRAM is preferred, so
ttm_bo_validate() migrates the buffer from GTT into VRAM.  While the
exporting device is runtime suspended its SDMA rings are down and the
move fails:

  amdgpu: Move buffer fallback to memcpy unavailable

An importer on a second GPU reaches this holding no runtime PM
reference on the exporter, e.g. a compositor on the APU submitting a
frame that references a buffer exported by an idle dGPU:

  amdgpu_cs_ioctl -> amdgpu_cs_parser_bos -> amdgpu_cs_bo_validate
    -> ttm_bo_validate -> amdgpu_bo_move -> dma_buf_map_attachment
      -> amdgpu_dma_buf_map -> ttm_bo_validate -> amdgpu_bo_move

Pinning a dma-buf into VRAM has the same requirement, which
commit 030631e97b ("drm/amdgpu: revert "take runtime pm reference
when we attach a buffer" v2") called out as the one case that would
need the reference back.

Take it in attach and drop it in detach.  pm_runtime_get_if_active()
never resumes the device, so it cannot deadlock against the reservation
taken during resume, which is why the old pm_runtime_get_sync() had to
go.  If the device is not active, clear peer2peer instead: the buffer
then stays in GTT, which remains accessible while the GPU is powered
down.  If runtime PM is disabled, take a plain reference so the put in
detach stays balanced.

Fixes: 030631e97b ("drm/amdgpu: revert "take runtime pm reference when we attach a buffer" v2")
Suggested-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
Assisted-by: Claude:Opus-5 [Claude Code]
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:28 -04:00
Alex Deucher
6443771066 MAINTAINERS: update git tree for radeon, amdgpu, amdkfd
Point to the new repo on gitlab.

Cc: christian.koenig@amd.com
Cc: felix.kuehling@amd.com
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
5319f554f8 drm/amdgpu/sdma: Always handle kernel queues in amdgpu_sdma_reset_engine()
Remove the caller_handles_kernel_queues argument from
the amdgpu_sdma_reset_engine() function and make it
always handle kernel queues.

Now the SDMA recovery sequence is more consistent
between callers for the KFD as follows.
Before recovery: first the KFD is suspended,
then the SDMA queue contents are backed up.
After recovery: first the SDMA queue contents
are restored, then the KFD is resumed.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
13e47c31e5 drm/amdgpu/sdma: Move SDMA v5.x queue reset to common code
The code was exactly the same between SDMA v5.0 and v5.2
furthermore the exact same implementation can be shared
between all SDMA versions that don't use MES.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
973a50908b drm/amdgpu/sdma: Clear SDMA rings after reset before starting them
The ring contains commands that were emitted before the reset.
These need to be cleared to make sure the HW doesn't execute
them, because they are garbage at this point.

Note that the ring reset helpers will re-emit the commands
that are necessary after the reset.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
de73eb26f9 drm/amdgpu: Add amdgpu_ring_clear_ring_and_ptrs()
A new helper function which clears the contents of
a ring and the relevant pointers such as rptr/wptr.

Suggested-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
3eb5587e13 drm/amdgpu/sdma: Remove unnecessary guilty tracking of SDMA queues
amdgpu_sdma_reset_engine() saves and restores contents of
both the SDMA gfx queue and the paging queue, so it's
not necessary to track which queue was guilty anymore.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
0518c66cf8 drm/amdgpu/sdma: Fix executing duplicate commands after recovery on SDMA v4.4.2
SDMA v4.4.2 had a custom recovery implementation that
tried to keep ring contents and restore the rptr after
an SDMA soft reset. Later it was changed to use the
more common amdgpu_sdma_reset_engine() implementation.

Currently, SDMA v4.4.2 may execute some commands twice
after a recovery:

1. From the old ring buffer contents at the restored rptr
2. From the contents restored by amdgpu_sdma_reset_engine()
   that calls the ring reset helper functions.

Fix that by removing the code that restores rptr.
This is not needed anymore because amdgpu_sdma_reset_engine()
already saves and restores the contents of both the SDMA gfx
and paging rings, so there is no need to do anything extra.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
5992cc6811 drm/amdgpu/sdma: Remove superfluous rlc_resume and rlc_stop functions
Every SDMA generation has an rlc_resume and rlc_stop function
which are not doing anything.

Starting from CIK, the SDMA engine supports additional queues
which are called "SDMA compute" or "RLC" queues, and these
queues are used by the KFD, and configured using the HWS.
There is nothing for the kernel driver to do for these.

Let's delete the functions that don't do anything.
In case of SDMA v4.0 and v4.4.2 let's move the init_pg()
call to the start() function.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Timur Kristóf
088c6a324d drm/amdgpu/sdma: Remove unimplemented soft_reset() for SDMA and SI DMA
These functions are not called from anywhere
and don't do anything. Let's delete them.

Also remove the srbm_soft_reset field from amdgpu_sdma
which is not set anywhere anymore.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Vladimir Marioukhine
b1f9601237 drm/amdkfd: implement restore_mqd callbacks for GFX12/12.1
kfd_mqd_manager_v12.c (GFX 12.0) and kfd_mqd_manager_v12_1.c (GFX 12.1)
do not implement restore_mqd callbacks, leaving the function pointers
NULL and causing CRIU restore to return -EOPNOTSUPP on GFX12.

Implement restore_mqd for both compute and SDMA queues in
kfd_mqd_manager_v12.c and kfd_mqd_manager_v12_1.c, modeled after the
GFX 11 implementation with the following improvements:
- update cp_mqd_base_addr_lo/hi to the newly allocated MQD address,
  fixing a pre-existing gap shared with v11 where the in-MQD copy
  still pointed at the old checkpoint-time address after restore
- memset the full allocation before memcpy for compute queues to avoid
  stale data in the GTT sub-allocator tail; SDMA MQDs use sizeof(*m)
  since they are packed at mqd_size stride in a shared BO

checkpoint_mqd registration is deferred to a follow-up patch that also
implements get_checkpoint_info, so that checkpoint and restore are
enabled together as a complete and testable unit.

Note: GFX12.1 restore handles XCC0 only. Multi-XCC CRIU restore is
currently unreachable due to a separate validation issue in
kfd_criu_restore_queue(). A pr_warn_once() is emitted if a multi-XCC
device is encountered.

Signed-off-by: Vladimir Marioukhine <Vladimir.Marioukhine@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
David Belanger
2753320ced drm/amdkfd: Disable gfxoff for CU occupancy
Disable gfxoff while collecting CU occupancy data.

Reported-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: David Belanger <david.belanger@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
David Belanger
940850827f drm/kfd: Add CU occupancy support to GFX10 and GFX10.3
Port changes from GFX9 to GFX10/GFX10.3 mostly as-is.
Minor changes to register access code.

Assisted-by: Claude:sonnet-4-6
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: David Belanger <david.belanger@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
David Francis
3d5f28824d drm/amdgpu: Add trace events for pid register/deregister
Some debugging applications need to track when a process starts
or stops using the amdgpu driver. For those processes, add ftrace
events that track when a amdgpu_vm task info is changed or destroyed.

v2: Deregister in fini, not destroy.

v3: Also report render minor and major

cc: Sunil Khatri <Sunil.Khatri@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Taimur Hassan
c3c902263f drm/amd/display: Promote DC to 3.2.398
This version brings along the following updates:

 - Expand amdgpu_dm KUnit coverage across connector init, sink stream
   creation, FreeSync caps, forced atomic commit, plane modifiers, cursor
   updates, panic flush, MST connector creation, AUX transfers, link
   bandwidth readback and MST DSC configuration.
 - Refactor RMCM into a separate module.
 - Decouple cursor offload hwss executors from pipe context.
 - Decouple HUBP_UPDATE_PLANE_ADDR from pipe_ctx.
 - Rename lock_and_validation_needed to needs_dc_state_realloc.
 - Drop the dead update_type param from update_planes_and_stream_adapter.
 - Attach only plane updates and stream updates that actually changed.
 - Unify fast update classification paths.
 - Request DMUB HW cursor offload.
 - Program DCC as part of address update.
 - Update LLS and UPSP programming paths.
 - Add lock-free memory pool.
 - Add instance field to struct mpc and struct dccg.
 - Cleanup DMUB command submission interfaces.
 - Add inbox0 HW lock helpers for DCN35.
 - Atomize IRQ register read/modify/write ops.
 - Add Replay cumulative residency query.
 - Add urgent assertion counter probe.
 - Add debug option to force optional UCLK support.
 - Force DSC to 8bpp for SST and MST DP tunneling over USB4.
 - Honor forced RGB pixel encoding.
 - Add option for certain panels to disable FEC.
 - Cap DML2.1 vmin ODM combine at 2:1 for eDP.
 - Add is_odm_enabled callback to skip init_odm on active ODM pipes.
 - Remove MALL capabilities from DCN42B.
 - Skip MALL calculations when there is no MALL.
 - Enable power gating on dcn42b.
 - Remove SDPIF_PORT_CONTROL programming for DCN31/35/42.
 - Enable back alt-ch.
 - Flush ISM work before releasing the stream.
 - Fix HDMI FRL audio enable.
 - Fix peak bandwidth measurement sequence.
 - Bound the DSC power gating loop by num_dsc.
 - Cast DP DTO pixel clock math to avoid overflow and narrowing.
 - Use unsigned types for FRL cap check params and HPO read_state.
 - Return success status from check_mode_supported.
 - Add SPDX license identifier to dcn30_dpp_cm.c.

Acked-by: Tom Chung <chiahsuan.chung@amd.com>
Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Chenyu Chen
fb8d8c5b00 drm/amd/display: Use unsigned types for FRL cap check params and HPO read_state
[Why]
Commit c3fb1fb9e6 ("drm/amd/display: Fix warnings") aligned the
signedness of a large number of DC values, but two hunks of the original
change were not carried over:

- struct frl_cap_chk_params_fixed31_32 still declares audio_packet_type,
  h_active and h_blank as int. All three only ever hold non-negative
  values: h_active and h_blank are HDMI timing quantities counted in
  pixels, and audio_packet_type is only compared against the positive
  HDMI audio packet type constants 0x02, 0x07, 0x08, 0x09 and 0x0e in
  frl_capacity_computations_common().

- hpo_enc3_read_state() still declares pixel_encoding, color_depth and
  odm_combine as int and passes their addresses to REG_GET_2()/REG_GET(),
  whose generic_reg_get*() backends take uint32_t *. The mismatch is only
  hidden by the explicit (uint32_t *) cast inside the REG_GET macros. The
  DCN401 equivalent, hpo_enc401_read_state(), already uses uint32_t.

[How]
Widen the three struct fields to unsigned int/uint32_t and the three
locals to uint32_t so the types match how the values are produced and
consumed. No computed value changes.

Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Rafal Ostrowski
30ca154558 drm/amd/display: Unify fast update classification paths
[Why]
The dc_fast_update intermediate struct created code duplication and
complexity with multiple classification paths (populate_fast_updates,
fast_nonaddr_updates_exist, full_update_required). This refactoring
simplifies the update classification system by consolidating to a
single path while maintaining compatibility.

[How]
Remove entire dc_fast_update struct and associated helper functions:
- populate_fast_updates
- fast_nonaddr_updates_exist
- full_update_required

Refactor check_update_surfaces_for_stream as the
single classification path with explicit handling for func_shaper,
lut3d_func, cursor_csc_color_matrix_change, and
scaler_sharpener_update. Add a reserved bitfield to the
stream_update_flags union for completeness guards. Extract
dc_check_address_only_update and dc_check_update_surfaces_for_stream
as public.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Rafal Ostrowski <rafal.ostrowski@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Tom Chung
c615f0715b drm/amd/display: Add inbox0 HW lock helpers for DCN35
Add dcn35_dmub_hw_control_lock() and dcn35_dmub_hw_control_lock_fast(),
a SW lock mechanism to prevent racing between driver and FW.

The helpers are not wired into dcn35_funcs/dcn351_funcs yet, so there is
no functional change: DCN3.5/3.5.1/3.6 keep using the existing inbox1
lock path. Enabling them will come in a follow-up patch.

Reviewed-by: Ray Wu <ray.wu@amd.com>
Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
James Lin
0575f53925 drm/amd/display: Cast DP DTO pixel clock math to avoid overflow and narrowing
[Why]
Commit 0421fc6ab3 ("drm/amd/display: fix __udivdi3 link error") switched
get_dp_dto_frequency_100hz() and dcn401_get_dp_dto_frequency_100hz() to
div_u64() but dropped the original explicit casts, leaving two issues:

- In get_dp_dto_frequency_100hz(), "clock_hz * dp_dto_ref_khz * 10" is
  computed in 32-bit unsigned arithmetic (both operands are unsigned int)
  before being stored into the u64 temp, so the product can overflow
  before it is widened (flagged by Coverity OVERFLOW_BEFORE_WIDEN).
- div_u64() returns a u64 that is assigned directly to the unsigned int
  *pixel_clk_100hz, an implicit narrowing conversion that trips
  -Wconversion (possible loss of data) on stricter builds.

[How]
Cast clock_hz to unsigned long long so the multiplication is performed in
64-bit, and make the u64 -> unsigned int narrowing explicit with an
(unsigned int) cast on the div_u64() results in both functions. The
computed values are unchanged.

Fixes: 0421fc6ab3 ("drm/amd/display: fix __udivdi3 link error")
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Signed-off-by: James Lin <PingLei.Lin@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:27 -04:00
Ilya Bakoulin
d4e5df4d7e drm/amd/display: Fix HDMI FRL audio enable
[Why/How]
The APG_CLOCK_EN bit can stay at 0 in some cases when going between
DPMS off and DPMS on.

Add APG_CLOCK_EN to audio_mute_control functions to make sure it gets
programmed.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Ovidiu Bunea
fd81d335f0 drm/amd/display: Add condition to skip MALL calculations if there is no MALL
[Why & How]
DCN42 has 0 bytes allocated for MALL, but this results in a 0 <= 0 comparison in
CalculateMALLUseForStaticScreen(), which blindly returns true.

This causes DML to calculate with is_using_mall_for_ss[n] = true.
Example:
0 + 0 <= 0  ->  true
        |
        v
   is_using_mall_for_ss[1] = true
        |
        v
   use_one_row_for_frame[1] = true
   PTE_BUFFER_MODE[1]       = true
        |
        v
   dpte_row_height    :     128  ->       808
   dpte_row_width_ub  : 196,608  -> 1,204,224
        |
        +--> DST_Y_PER_PTE_ROW_NOM_L = 808
        |
        +--> N_groups = ceil(1,204,224 / 65,536 / 2) = 10
                 |
                 v
        REFCYC_PER_PTE_GROUP_NOM_L = 8416 (0x20E0)

Currently, DML does not plumb out the programming for PTE_BUFFER_MODE and FORCE_ONE_ROW_FOR_FRAME,
but even adding that programming does not enable the mode to work with these values.

The simplest fix is to just block any opportunistic MALL calculations.

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Ovidiu Bunea <ovidiu.bunea@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Alvin Lee
636417afb0 drm/amd/display: Return success status from check_mode_supported
[Description]
dml21_top_utm_check_mode_supported must return the success status from
the mode support result otherwise the caller will believe that mode
support always returns true. This can cause issues where mode support
returns true, where mode programming returns false.

Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Leo Li
70de0a0216 drm/amd/display: Atomize IRQ register read/modify/write ops
[Why]

The OTG_GLOBAL_SYNC_STATUS register controls various HW IRQ sources for
the output timing generator (OTG). VUPDATE_NO_LOCK is one of them.

To enable the IRQ, driver sets the VUPDATE_NO_LOCK_EN bit in the
GLOBAL_SYNC_STATUS register.

To ack the IRQ after it fires, the driver sets the VUPDATE_NO_LOCK_CLEAR
bit in the same GLOBAL_SYNC_STATUS register.

The bit sets are done through read/modify/write operations, which are
not atomic. Thus, the following race is possible:

    Thread A:                       IRQ handler:
                                    *HW IRQ fires*
    # IRQ disable
    val = read(GLOBAL_SYNC_STATUS)
    unset(val, VUPDATE_NO_LOCK_EN)
    write(val, GLOBAL_SYNC_STATUS)
                                    # ACK reads VUPDATE_NO_LOCK_EN unset
                                    val1 = read(GLOBAL_SYNC_STATUS)
                                    set(val1, VUPDATE_NO_LOCK_CLEAR)
    # IRQ enable
    val = read(GLOBAL_SYNC_STATUS)
    set(val, VUPDATE_NO_LOCK_EN)
    write(val, GLOBAL_SYNC_STATUS)
                                    # BAD! clears VUPDATE_NO_LOCK_EN
                                    write(val1, GLOBAL_SYNC_STATUS)

Regarding the tagged Fixes: change, it appears the change made this race
more likely to occur. Since VUPDATE_NO_LOCK is now the sole IRQ source
for vblank handling, a single race on high refresh panels can lead to a
time out.

[How]

The GLOBAL_SYNC_STATUS register is only one example, other IRQ control
registers also share the same scheme. On top of GLOBAL_SYNC_STATUS,
let's clean up those as well.

To keep things simple, Let's atomize the IRQ rmw ops via a single
driver-wide spinlock. Due to the small scope of this lock, it is
unlikely to cause noticeable overhead on top of all the existing locking
within the IRQ set/handle paths.

Since DM is responsible for locking, wrap dc_interrupt_set/ack with the
spinlock in the new amdgpu_dm_irq_set/ack functions. Migrate/drop all
references in DM to dc_interrupt_set/ack to use amdgpu_dm_irq_set/ack
instead.

Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5616
Fixes: c87e6635d2 ("drm/amd/display: consolidate DCN vblank/flip handling onto vupdate_no_lock")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Gabe Teeger
3366975818 drm/amd/display: Remove MALL capabilities from DCN42B bounding box
[Why]
DCN42B has no MALL, but MALL capabilities are non-zero.

[How]
Zero out MALL capabilities in the dcn42b bounding box.

Reviewed-by: Matthew Stewart <matthew.stewart2@amd.com>
Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Gabe Teeger <gabe.teeger@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Gabe Teeger
60484b2f02 drm/amd/display: Remove MALL capabilities from DCN42B
[Why]
DCN42B has no MALL, but the resource file advertised MALL and CAB
sizes. SubVP was also enabled even though its phantom surfaces
are allocated in MALL.

[How]
Drop the MALL and SubVP caps, the dml2_options svp_pstate and
mall_cfg setup, and the add_phantom_pipes and
calculate_mall_ways_from_bytes callbacks. Disable SubVP.

Reviewed-by: Matthew Stewart <matthew.stewart2@amd.com>
Signed-off-by: Gabe Teeger <gabe.teeger@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Tony Cheng
bbd277136c drm/amd/display: Add SPDX license identifier to dcn30_dpp_cm.c
[Why&How]
dcn30_dpp_cm.c carries the full MIT license text but no SPDX tag. Add
the SPDX-License-Identifier line so the file matches the rest of the
tree.

Reviewed-by: Jun Lei <jun.lei@amd.com>
Signed-off-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Tony Cheng
5d26de23ef drm/amd/display: Add instance field to struct dccg
[Why]
struct dccg has no instance identifier, unlike other DC hardware
blocks. Debug and tracing helpers need one to identify the block.

[How]
Add an inst member to struct dccg and initialize it to 0 in every
dccgX_create(), since there is one DCCG instance per ASIC.

Reviewed-by: Jun Lei <jun.lei@amd.com>
Signed-off-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Alvin Lee
094108908d drm/amd/display: Program DCC as part of address update
[Description]
- DCC register is latched on the surface address register being updated
- In this case couple the DCC programming and the address update
  together to ensure the DCC programming is always taken as expected
- Update address programming function to take in DCC bool, use for
  DCN6+ and leave older DCN unchanged.

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Wang, Sung-huai
a3bc27586d drm/amd/display: Add is_odm_enabled callback to skip init_odm on active ODM pipes
[Why]
dcn10_init_pipes unconditionally calls init_odm on all enabled TGs,
resetting ODM combine state even when it should be preserved.

[How]
Add is_odm_enabled callback to timing_generator_funcs and
guard init_odm to skip when ODM is already active.

Reviewed-by: Aric Cyr <aric.cyr@amd.com>
Signed-off-by: Danny Wang <Danny.Wang@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Leo Chen
ec0c15a270 drm/amd/display: Cap DML2.1 vmin ODM combine at 2:1 for eDP
[Why]
Currently in DML2.1, by design, the DPMs are unpinned when optimizing
for Vmin PMO. This leads to an issue on DCN42 on specific panels (e.g. 4k144 eDP)
where ODM4:1 is applied unexpectedly, which affects the urgent bandwidth required,
raises DCFCLK to DPM1, and thus blocks Z8.

[How]
Clamp the ODM combine limit to 2 for eDP streams directly in
pmo_dcn4_fams2_optimize_for_vmin()

Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Leo Chen <leo.chen@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Ray Wu
2f08de495c drm/amd/display: Flush ISM work before releasing the stream
[Why]
ISM timers are not tied to the atomic commit, so a timer armed before a
DPMS off can still fire after the stream is released. The external display
check in dcn35_apply_idle_power_optimizations() loops over the active
streams, so with none left it never runs and idle is allowed on an
external-only system.

[How]
Wait out pending and in-flight ISM work before dc_stream_release(); dc_lock
is not held there, so the sync wait is safe. Rename amdgpu_dm_ism_fini() to
amdgpu_dm_ism_flush() and assert dc_lock is not held.

Assisted-by: Cursor:Claude-Opus-5
Reviewed-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
James Lin
acb623f3c2 drm/amd/display: Drop dead update_type param from update_planes_and_stream_adapter
[Why & How]
The adapter never read update_type; DC derives the update type itself inside
dc_update_planes_and_stream(). Drop the dead parameter from the prototype, the
two callers and the KUnit tests.

Reviewed-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: James Lin <pinglei.lin@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
James Lin
acc92b3aad drm/amd/display: Send stream_update to DC only when it changed
[Why & How]
Track stream_update_needed and pass &bundle->stream_update to DC only when a
real stream property was actually written (native-cursor disable, cursor
position/attributes, VRR infopacket, modeset src/dst, color management, ABM
level); otherwise pass NULL. An address-only flip then carries no
stream_update and stays on the FAMS2 offload path.

Reviewed-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: James Lin <pinglei.lin@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
James Lin
555641725f drm/amd/display: Request DMUB HW cursor offload
[Why & How]
Request cursor offload in dc_config and initialize it after DMUB is up
(dc_dmub_srv_cursor_offload_init), which self-gates on the firmware
cursor_offload_v1_support capability, so cursor programming no longer takes
the inbox0 lock on alt-in-use streams.

Reviewed-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: James Lin <pinglei.lin@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
James Lin
123f78c8fa drm/amd/display: Attach only plane updates that actually changed
[Why & How]
Cache the last programmed dc_flip_addrs/dc_plane_info/dc_scaling_info in
dm_plane_state and carry them across atomic_duplicate_state. In
amdgpu_dm_commit_planes() attach each flip_addr/plane_info/scaling_info
surface update only when it differs from the cache (memcmp), so an
address-only flip sends no plane_info/scaling_info update and stays on the
FAMS2 offload path.

Reviewed-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: James Lin <pinglei.lin@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
James Lin
e3fe350998 drm/amd/display: Rename lock_and_validation_needed to needs_dc_state_realloc
[Why & How]
Split the boolean's two meanings: it only tracks whether the commit needs
to rebuild the dc_state and take the global lock, not the update magnitude.
Rename it so the name reflects that; no functional change.

Reviewed-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: James Lin <pinglei.lin@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00
Dominik Kaszewski
6f74688d7e drm/amd/display: Add lock-free memory pool
[Why]
Two memory limitations - limited stack size and heap allocations
not allowed in interrupts - combined together lead to scratch
structures and buffers scattered throughout the code, requiring
piping them through interfaces.

[How]
* OS-provided lock-free lists still need external locking for some
operations, requiring a custom implementation.
* Implement memory pool which can preallocate a number of blocks
with given size, then later "allocate" from them without any heap use.
* Pool implemented as lock-free Treiber stack to avoid operations
being blocked by suspended thread, including a same-thread interrupt
exemption causing an indefinite block.
* Indexed free list and generation counter protect against ABA
data corruption.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Dominik Kaszewski <dominik.kaszewski@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2026-09-17 11:38:26 -04:00