Re: [PATCH v6] drm/amd/amdgpu: remove duplicated code in gfx_v11 and gfx_v12
Alex Deucher <[email protected]> Wed, 29 Jul 2026 10:26:56 -0400
| Newsgroups | org.freedesktop.lists.amd-gfx,org.freedesktop.lists.dri-devel |
|---|---|
| Message-ID | <CADnq5_PEZTzk4KXDE05LjidaobzGRLDWK1mDxwBBVvVwu1s4qQ@mail.gmail.com> |
Applied. Thanks! On Wed, Jul 29, 2026 at 9:49 AM Ulisses Paixao <[email protected]> wrote: > > The functions gfx_v11_0_handle_priv_fault and > gfx_v12_0_handle_priv_fault share the same logic for searching and > triggering a scheduler fault on a ring. This patch moves the shared > ring-searching logic to a common function, amdgpu_gfx_handle_priv_fault, > in amdgpu_gfx.c. The hardware-specific decoding of ring IDs remains in > the version-specific files to maintain proper architectural separation. > > Signed-off-by: Ulisses Paixao <[email protected]> > Co-developed-by: Felipe Sousa <[email protected]> > Signed-off-by: Felipe Sousa <[email protected]> > Reviewed-by: Christian König <[email protected]> > --- > v6: > Updated code with latest changes from amd-staging-drm-next. > > v5: > Return early on adv->gfx.disable_kq check. > > v4: > Restore the adev->gfx.disable_kq check to prevent falsely triggering > scheduler faults on idle kernel rings when MES is managing user queues. > > v3: > Return early if the ring is found in the gfx rings loop. > > v2: > Keep the HW-specific decoding in gfx_v11_0.c and gfx_v12_0.c. > Remove the redundant check for adev->gfx.disable_kq. > Simplify the search loop in amdgpu_gfx_handle_priv_fault to iterate over > all gfx and compute rings without a switch statement. > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 53 +++++++++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 3 ++ > drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 49 +++-------------------- > drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 50 +++-------------------- > 4 files changed, 66 insertions(+), 89 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c > index 9d3b40c38..9ff0829ac 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c > @@ -34,6 +34,7 @@ > #include "amdgpu_xcp.h" > #include "amdgpu_xgmi.h" > #include "amdgpu_mes.h" > +#include "amdgpu_userq.h" > #include "mes_userqueue.h" > #include "nvd.h" > > @@ -855,6 +856,58 @@ int amdgpu_gfx_enable_kgq(struct amdgpu_device *adev, int xcc_id) > return r; > } > > +/** > + * amdgpu_gfx_handle_priv_fault - Handle privileged instruction fault > + * > + * @adev: amdgpu_device pointer > + * @entry: interrupt vector entry containing fault information > + * @me_id: micro-engine ID of the faulty ring > + * @pipe_id: pipe ID of the faulty ring > + * @queue_id: queue ID of the faulty ring > + * > + * This function handles privileged instruction faults by identifying > + * the faulty ring (gfx or compute) and triggering a scheduler fault > + */ > +void amdgpu_gfx_handle_priv_fault(struct amdgpu_device *adev, > + struct amdgpu_iv_entry *entry, > + u8 me_id, u8 pipe_id, u8 queue_id) > +{ > + struct amdgpu_ring *ring; > + int i; > + > + /* > + * Try KQ first by ring_id (HW slot is authoritative). The > + * KMD compute_hqd_mask contract guarantees KCQ and user queues > + * never share a HW slot. > + */ > + if (!adev->gfx.disable_kq) { > + for (i = 0; i < adev->gfx.num_gfx_rings; i++) { > + ring = &adev->gfx.gfx_ring[i]; > + if (ring->me == me_id && ring->pipe == pipe_id && > + ring->queue == queue_id) { > + drm_sched_fault(&ring->sched); > + return; > + } > + } > + > + for (i = 0; i < adev->gfx.num_compute_rings; i++) { > + ring = &adev->gfx.compute_ring[i]; > + if (ring->me == me_id && ring->pipe == pipe_id && > + ring->queue == queue_id) { > + drm_sched_fault(&ring->sched); > + return; > + } > + } > + } > + > + u32 doorbell_offset = entry->src_data[0] & AMDGPU_CTXID0_DOORBELL_ID_MASK; > + > + /* No KQ matched: HW slot is a MES-scheduled user queue. */ > + if (adev->enable_mes && doorbell_offset) > + amdgpu_userq_process_reset_irq(adev, entry->pasid, > + doorbell_offset); > +} > + > static void amdgpu_gfx_do_off_ctrl(struct amdgpu_device *adev, bool enable, > bool no_delay) > { > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h > index aefd4f03b..c15f45a73 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h > @@ -620,6 +620,9 @@ bool amdgpu_gfx_is_high_priority_graphics_queue(struct amdgpu_device *adev, > struct amdgpu_ring *ring); > bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev, int me, > int pipe, int queue); > +void amdgpu_gfx_handle_priv_fault(struct amdgpu_device *adev, > + struct amdgpu_iv_entry *entry, > + u8 me_id, u8 pipe_id, u8 queue_id); > void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable); > void amdgpu_gfx_off_ctrl_immediate(struct amdgpu_device *adev, bool enable); > int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value); > diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c > index 0cbbdc369..489e0c97e 100644 > --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c > +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c > @@ -6710,52 +6710,13 @@ static int gfx_v11_0_set_priv_inst_fault_state(struct amdgpu_device *adev, > static void gfx_v11_0_handle_priv_fault(struct amdgpu_device *adev, > struct amdgpu_iv_entry *entry) > { > - u32 doorbell_offset = entry->src_data[0] & AMDGPU_CTXID0_DOORBELL_ID_MASK; > + u8 me_id, pipe_id, queue_id; > > - /* > - * Try KQ first by ring_id (HW slot is authoritative). The > - * KMD compute_hqd_mask contract guarantees KCQ and user queues > - * never share a HW slot. > - */ > - if (!adev->gfx.disable_kq) { > - u8 me_id = (entry->ring_id & 0x0c) >> 2; > - u8 pipe_id = (entry->ring_id & 0x03) >> 0; > - u8 queue_id = (entry->ring_id & 0x70) >> 4; > - struct amdgpu_ring *ring; > - int i; > - > - switch (me_id) { > - case 0: > - for (i = 0; i < adev->gfx.num_gfx_rings; i++) { > - ring = &adev->gfx.gfx_ring[i]; > - if (ring->me == me_id && ring->pipe == pipe_id && > - ring->queue == queue_id) { > - drm_sched_fault(&ring->sched); > - return; > - } > - } > - break; > - case 1: > - case 2: > - for (i = 0; i < adev->gfx.num_compute_rings; i++) { > - ring = &adev->gfx.compute_ring[i]; > - if (ring->me == me_id && ring->pipe == pipe_id && > - ring->queue == queue_id) { > - drm_sched_fault(&ring->sched); > - return; > - } > - } > - break; > - default: > - BUG(); > - break; > - } > - } > + me_id = (entry->ring_id & 0x0c) >> 2; > + pipe_id = (entry->ring_id & 0x03) >> 0; > + queue_id = (entry->ring_id & 0x70) >> 4; > > - /* No KQ matched: HW slot is a MES-scheduled user queue. */ > - if (adev->enable_mes && doorbell_offset) > - amdgpu_userq_process_reset_irq(adev, entry->pasid, > - doorbell_offset); > + amdgpu_gfx_handle_priv_fault(adev, entry, me_id, pipe_id, queue_id); > } > > static int gfx_v11_0_priv_reg_irq(struct amdgpu_device *adev, > diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c > index b3887c526..32cd9ad66 100644 > --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c > +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c > @@ -5041,53 +5041,13 @@ static int gfx_v12_0_set_priv_inst_fault_state(struct amdgpu_device *adev, > static void gfx_v12_0_handle_priv_fault(struct amdgpu_device *adev, > struct amdgpu_iv_entry *entry) > { > - u32 doorbell_offset = entry->src_data[0] & AMDGPU_CTXID0_DOORBELL_ID_MASK; > + u8 me_id, pipe_id, queue_id; > > - /* > - * Try KQ first by ring_id; UQ as fallback. KCQ and UQ never share > - * a HW slot (compute_hqd_mask contract). > - */ > - if (!adev->gfx.disable_kq) { > - u8 me_id, pipe_id, queue_id; > - struct amdgpu_ring *ring; > - int i; > - > - me_id = (entry->ring_id & 0x0c) >> 2; > - pipe_id = (entry->ring_id & 0x03) >> 0; > - queue_id = (entry->ring_id & 0x70) >> 4; > - > - switch (me_id) { > - case 0: > - for (i = 0; i < adev->gfx.num_gfx_rings; i++) { > - ring = &adev->gfx.gfx_ring[i]; > - if (ring->me == me_id && ring->pipe == pipe_id && > - ring->queue == queue_id) { > - drm_sched_fault(&ring->sched); > - return; > - } > - } > - break; > - case 1: > - case 2: > - for (i = 0; i < adev->gfx.num_compute_rings; i++) { > - ring = &adev->gfx.compute_ring[i]; > - if (ring->me == me_id && ring->pipe == pipe_id && > - ring->queue == queue_id) { > - drm_sched_fault(&ring->sched); > - return; > - } > - } > - break; > - default: > - BUG(); > - break; > - } > - } > + me_id = (entry->ring_id & 0x0c) >> 2; > + pipe_id = (entry->ring_id & 0x03) >> 0; > + queue_id = (entry->ring_id & 0x70) >> 4; > > - /* No KQ matched: HW slot is a MES-scheduled user queue. */ > - if (adev->enable_mes && doorbell_offset) > - amdgpu_userq_process_reset_irq(adev, entry->pasid, > - doorbell_offset); > + amdgpu_gfx_handle_priv_fault(adev, entry, me_id, pipe_id, queue_id); > } > > static int gfx_v12_0_priv_reg_irq(struct amdgpu_device *adev, > -- > 2.34.1 >