drm/amdgpu: enable IH ring 1 and ring 2 for navi
Support added into IH to enable ring1 and ring2 for navi10_ih. Signed-off-by: Alex Sierra <alex.sierra@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
b635ae8744
commit
ab51801206
@@ -51,6 +51,22 @@ static void navi10_ih_enable_interrupts(struct amdgpu_device *adev)
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
|
||||
adev->irq.ih.enabled = true;
|
||||
|
||||
if (adev->irq.ih1.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
|
||||
RB_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
|
||||
adev->irq.ih1.enabled = true;
|
||||
}
|
||||
|
||||
if (adev->irq.ih2.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
|
||||
RB_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
|
||||
adev->irq.ih2.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +88,31 @@ static void navi10_ih_disable_interrupts(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
|
||||
adev->irq.ih.enabled = false;
|
||||
adev->irq.ih.rptr = 0;
|
||||
|
||||
if (adev->irq.ih1.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
|
||||
RB_ENABLE, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
|
||||
adev->irq.ih1.enabled = false;
|
||||
adev->irq.ih1.rptr = 0;
|
||||
}
|
||||
|
||||
if (adev->irq.ih2.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
|
||||
RB_ENABLE, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
|
||||
adev->irq.ih2.enabled = false;
|
||||
adev->irq.ih2.rptr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static uint32_t navi10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
|
||||
@@ -97,6 +138,25 @@ static uint32_t navi10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl
|
||||
return ih_rb_cntl;
|
||||
}
|
||||
|
||||
static uint32_t navi10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 ih_doorbell_rtpr = 0;
|
||||
|
||||
if (ih->use_doorbell) {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, OFFSET,
|
||||
ih->doorbell_index);
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR,
|
||||
ENABLE, 1);
|
||||
} else {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR,
|
||||
ENABLE, 0);
|
||||
}
|
||||
return ih_doorbell_rtpr;
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_irq_init - init and enable the interrupt ring
|
||||
*
|
||||
@@ -111,7 +171,7 @@ static uint32_t navi10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl
|
||||
static int navi10_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ih_ring *ih = &adev->irq.ih;
|
||||
u32 ih_rb_cntl, ih_doorbell_rtpr, ih_chicken;
|
||||
u32 ih_rb_cntl, ih_chicken;
|
||||
u32 tmp;
|
||||
|
||||
/* disable irqs */
|
||||
@@ -149,22 +209,52 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
|
||||
|
||||
ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
|
||||
if (ih->use_doorbell) {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, OFFSET,
|
||||
ih->doorbell_index);
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, ENABLE, 1);
|
||||
} else {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, ENABLE, 0);
|
||||
}
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR,
|
||||
navi10_ih_doorbell_rptr(ih));
|
||||
|
||||
adev->nbio.funcs->ih_doorbell_range(adev, ih->use_doorbell,
|
||||
ih->doorbell_index);
|
||||
|
||||
ih = &adev->irq.ih1;
|
||||
if (ih->ring_size) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
|
||||
(ih->gpu_addr >> 40) & 0xff);
|
||||
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
ih_rb_cntl = navi10_ih_rb_cntl(ih, ih_rb_cntl);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
WPTR_OVERFLOW_ENABLE, 0);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
RB_FULL_DRAIN_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
|
||||
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1,
|
||||
navi10_ih_doorbell_rptr(ih));
|
||||
}
|
||||
|
||||
ih = &adev->irq.ih2;
|
||||
if (ih->ring_size) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
|
||||
(ih->gpu_addr >> 40) & 0xff);
|
||||
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
|
||||
ih_rb_cntl = navi10_ih_rb_cntl(ih, ih_rb_cntl);
|
||||
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
|
||||
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2,
|
||||
navi10_ih_doorbell_rptr(ih));
|
||||
}
|
||||
|
||||
|
||||
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
|
||||
CLIENT18_IS_STORM_CLIENT, 1);
|
||||
@@ -217,7 +307,15 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev,
|
||||
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
|
||||
goto out;
|
||||
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
|
||||
if (ih == &adev->irq.ih)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
|
||||
else if (ih == &adev->irq.ih1)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
|
||||
else if (ih == &adev->irq.ih2)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
|
||||
else
|
||||
BUG();
|
||||
|
||||
wptr = RREG32_NO_KIQ(reg);
|
||||
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
|
||||
goto out;
|
||||
@@ -233,7 +331,15 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev,
|
||||
wptr, ih->rptr, tmp);
|
||||
ih->rptr = tmp;
|
||||
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
if (ih == &adev->irq.ih)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
else if (ih == &adev->irq.ih1)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
else if (ih == &adev->irq.ih2)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
|
||||
else
|
||||
BUG();
|
||||
|
||||
tmp = RREG32_NO_KIQ(reg);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
WREG32_NO_KIQ(reg, tmp);
|
||||
@@ -333,8 +439,52 @@ static void navi10_ih_set_rptr(struct amdgpu_device *adev,
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
navi10_ih_irq_rearm(adev, ih);
|
||||
} else
|
||||
} else if (ih == &adev->irq.ih) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
|
||||
} else if (ih == &adev->irq.ih1) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr);
|
||||
} else if (ih == &adev->irq.ih2) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* navi10_ih_self_irq - dispatch work for ring 1 and 2
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @source: irq source
|
||||
* @entry: IV with WPTR update
|
||||
*
|
||||
* Update the WPTR from the IV and schedule work to handle the entries.
|
||||
*/
|
||||
static int navi10_ih_self_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
uint32_t wptr = cpu_to_le32(entry->src_data[0]);
|
||||
|
||||
switch (entry->ring_id) {
|
||||
case 1:
|
||||
*adev->irq.ih1.wptr_cpu = wptr;
|
||||
schedule_work(&adev->irq.ih1_work);
|
||||
break;
|
||||
case 2:
|
||||
*adev->irq.ih2.wptr_cpu = wptr;
|
||||
schedule_work(&adev->irq.ih2_work);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs navi10_ih_self_irq_funcs = {
|
||||
.process = navi10_ih_self_irq,
|
||||
};
|
||||
|
||||
static void navi10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->irq.self_irq.num_types = 0;
|
||||
adev->irq.self_irq.funcs = &navi10_ih_self_irq_funcs;
|
||||
}
|
||||
|
||||
static int navi10_ih_early_init(void *handle)
|
||||
@@ -342,6 +492,7 @@ static int navi10_ih_early_init(void *handle)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
navi10_ih_set_interrupt_funcs(adev);
|
||||
navi10_ih_set_self_irq_funcs(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -351,6 +502,12 @@ static int navi10_ih_sw_init(void *handle)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
bool use_bus_addr;
|
||||
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
|
||||
&adev->irq.self_irq);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* use gpu virtual address for ih ring
|
||||
* until ih_checken is programmed to allow
|
||||
* use bus address for ih ring by psp bl */
|
||||
@@ -363,6 +520,20 @@ static int navi10_ih_sw_init(void *handle)
|
||||
adev->irq.ih.use_doorbell = true;
|
||||
adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
|
||||
|
||||
r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->irq.ih1.use_doorbell = true;
|
||||
adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
|
||||
|
||||
r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->irq.ih2.use_doorbell = true;
|
||||
adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
|
||||
|
||||
r = amdgpu_irq_init(adev);
|
||||
|
||||
return r;
|
||||
@@ -373,6 +544,8 @@ static int navi10_ih_sw_fini(void *handle)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user