[PATCH 42/95] drm/amdgpu: Add UALink IH ring and enable interrupt
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Philip Yang <[email protected]> Register the UALink IRQ source with the IH subsystem. Hardware IH entries are re-queued onto a dedicated soft ring and drained by a work queue handler. Add the soft ring, worker, and delegate helper to the IRQ layer. Signed-off-by: Philip Yang <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 17 +++++ drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h | 7 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c | 82 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/ih_v7_0.c | 8 +++ 4 files changed, 112 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 91f1ca95ea543..dcf90a974326d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -264,6 +264,14 @@ static void amdgpu_irq_handle_ih_psp(struct work_struct *work) amdgpu_ih_process(adev, &adev->irq.ih_psp); } + +static void amdgpu_irq_handle_ih_ualink(struct work_struct *work) +{ + struct amdgpu_device *adev = container_of(work, struct amdgpu_device, + irq.ih_ualink_work); + + amdgpu_ih_process(adev, &adev->irq.ih_ualink); +} /** * amdgpu_msi_ok - check whether MSI functionality is enabled @@ -341,6 +349,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev) INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2); INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft); INIT_WORK(&adev->irq.ih_psp_work, amdgpu_irq_handle_ih_psp); + INIT_WORK(&adev->irq.ih_ualink_work, amdgpu_irq_handle_ih_ualink); /* Use vector 0 for MSI-X. */ r = pci_irq_vector(adev->pdev, 0); @@ -566,6 +575,14 @@ void amdgpu_irq_psp_delegate(struct amdgpu_device *adev, schedule_work(&adev->irq.ih_psp_work); } +void amdgpu_irq_ualink_delegate(struct amdgpu_device *adev, + struct amdgpu_iv_entry *entry, + unsigned int num_dw) +{ + amdgpu_ih_ring_write(adev, &adev->irq.ih_ualink, entry->iv_entry, num_dw); + schedule_work(&adev->irq.ih_ualink_work); +} + /** * amdgpu_irq_update - update hardware interrupt state * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h index deee64b69885d..c88431471c303 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h @@ -90,10 +90,10 @@ struct amdgpu_irq { bool msi_enabled; /* msi enabled */ /* interrupt rings */ - struct amdgpu_ih_ring ih, ih1, ih2, ih_soft, ih_psp; + struct amdgpu_ih_ring ih, ih1, ih2, ih_soft, ih_psp, ih_ualink; const struct amdgpu_ih_funcs *ih_funcs; struct work_struct ih1_work, ih2_work, ih_soft_work, - ih_psp_work; + ih_psp_work, ih_ualink_work; struct amdgpu_irq_src self_irq; /* gen irq stuff */ @@ -138,6 +138,9 @@ void amdgpu_irq_delegate(struct amdgpu_device *adev, void amdgpu_irq_psp_delegate(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry, unsigned int num_dw); +void amdgpu_irq_ualink_delegate(struct amdgpu_device *adev, + struct amdgpu_iv_entry *entry, + unsigned int num_dw); int amdgpu_irq_update(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type); int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c index 3fc11b49d9863..8ea34411f4227 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c @@ -63,6 +63,13 @@ int amdgpu_ualink_init(struct amdgpu_device *adev) return r; } + r = amdgpu_ualink_init_interrupt(adev); + if (r) { + dev_err(adev->dev, + "Failed to enable UALink irq: %d\n", r); + return r; + } + return 0; } @@ -3061,3 +3068,78 @@ void amdgpu_ualink_sw_fini(struct amdgpu_device *adev) adev->ualink.remote = NULL; } +static int amdgpu_ualink_process_irq(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + int handled = 1; + + dev_dbg(adev->dev, "%s client_id 0x%x src_id 0x%x ih\n", + entry->ih == &adev->irq.ih ? "ring" : "ualink soft ring", + entry->client_id, entry->src_id); + + /* Copy IH entry into ualink soft ring. */ + if (entry->ih == &adev->irq.ih) { + dev_dbg(adev->dev, "delegate to ualink irq soft ring\n"); + amdgpu_irq_ualink_delegate(adev, entry, 8); + return handled; + } + + /* + * Call amdgpu_ualink_interrupt handler + * amdgpu_ualink_interrupt(adev, entry); + */ + + return handled; +} + +static int amdgpu_ualink_set_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + u32 type, + enum amdgpu_interrupt_state state) +{ + /* + * Don't set register to enable/disable nHT controller interrupt. + * + * F/W running on MP2, which can always send cookie to IH block to + * interrupt driver. + */ + dev_dbg(adev->dev, "ualink interrupt %s\n", + state == AMDGPU_IRQ_STATE_ENABLE ? "enable" : "disable"); + return 0; +} + +static const struct amdgpu_irq_src_funcs ualink_irq_funcs = { + .set = amdgpu_ualink_set_irq_state, + .process = amdgpu_ualink_process_irq, +}; + +/* TODO: if move to header file soc21_enum.h */ +#define UALINK_IH_CLIENT_ID 0x1C +#define UALINK_IH_SOURCE_ID 0x0 + +/** + * amdgpu_ualink_init_interrupt - initialization of UALink IRQ + * @adev: amdgpu device pointer + * + * Registers the UALink interrupt source with the IH (Interrupt Handler) + * subsystem during early device initialization. This sets up the IRQ + * callback functions for handling remote interrupts from peer GPUs. + * + * Return: 0 on success, negative error code on failure + */ +int amdgpu_ualink_init_interrupt(struct amdgpu_device *adev) +{ + int r; + + dev_dbg(adev->dev, "init ualink irq client_id 0x%x src_id 0x%x\n", + UALINK_IH_CLIENT_ID, UALINK_IH_SOURCE_ID); + + adev->ualink.irq.num_types = 1; + adev->ualink.irq.funcs = &ualink_irq_funcs; + + r = amdgpu_irq_add_id(adev, UALINK_IH_CLIENT_ID, + UALINK_IH_SOURCE_ID, &adev->ualink.irq); + return r; +} + diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c index 6265ee4b0ff1e..7f4ef50195f6b 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c @@ -423,6 +423,9 @@ static int ih_v7_0_irq_init(struct amdgpu_device *adev) if (adev->irq.ih_psp.ring_size) adev->irq.ih_psp.enabled = true; + if (adev->irq.ih_ualink.ring_size) + adev->irq.ih_ualink.enabled = true; + return 0; } @@ -634,6 +637,11 @@ static int ih_v7_0_sw_init(struct amdgpu_ip_block *ip_block) if (r) return r; + dev_dbg(adev->dev, "ualink init ih_ualink\n"); + r = amdgpu_ih_ring_init(adev, &adev->irq.ih_ualink, sw_ring_size, true); + if (r) + return r; + r = amdgpu_irq_init(adev); return r; -- 2.55.0