Commit 8bb9eb48 authored by Christian König's avatar Christian König Committed by Alex Deucher

drm/amdgpu: add IH ring to ih_get_wptr/ih_set_rptr v2

Let's start to support multiple rings.

v2: decode IV is needed as well
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 73c97fa4
...@@ -137,7 +137,7 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih, ...@@ -137,7 +137,7 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
if (!ih->enabled || adev->shutdown) if (!ih->enabled || adev->shutdown)
return IRQ_NONE; return IRQ_NONE;
wptr = amdgpu_ih_get_wptr(adev); wptr = amdgpu_ih_get_wptr(adev, ih);
restart_ih: restart_ih:
/* is somebody else already processing irqs? */ /* is somebody else already processing irqs? */
...@@ -154,11 +154,11 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih, ...@@ -154,11 +154,11 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
ih->rptr &= ih->ptr_mask; ih->rptr &= ih->ptr_mask;
} }
amdgpu_ih_set_rptr(adev); amdgpu_ih_set_rptr(adev, ih);
atomic_set(&ih->lock, 0); atomic_set(&ih->lock, 0);
/* make sure wptr hasn't changed while processing */ /* make sure wptr hasn't changed while processing */
wptr = amdgpu_ih_get_wptr(adev); wptr = amdgpu_ih_get_wptr(adev, ih);
if (wptr != ih->rptr) if (wptr != ih->rptr)
goto restart_ih; goto restart_ih;
......
...@@ -50,15 +50,16 @@ struct amdgpu_ih_ring { ...@@ -50,15 +50,16 @@ struct amdgpu_ih_ring {
/* provided by the ih block */ /* provided by the ih block */
struct amdgpu_ih_funcs { struct amdgpu_ih_funcs {
/* ring read/write ptr handling, called from interrupt context */ /* ring read/write ptr handling, called from interrupt context */
u32 (*get_wptr)(struct amdgpu_device *adev); u32 (*get_wptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
void (*decode_iv)(struct amdgpu_device *adev, void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
struct amdgpu_iv_entry *entry); struct amdgpu_iv_entry *entry);
void (*set_rptr)(struct amdgpu_device *adev); void (*set_rptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
}; };
#define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) #define amdgpu_ih_get_wptr(adev, ih) (adev)->irq.ih_funcs->get_wptr((adev), (ih))
#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) #define amdgpu_ih_decode_iv(adev, iv) \
#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) (adev)->irq.ih_funcs->decode_iv((adev), (ih), (iv))
#define amdgpu_ih_set_rptr(adev, ih) (adev)->irq.ih_funcs->set_rptr((adev), (ih))
int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih, int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
unsigned ring_size, bool use_bus_addr); unsigned ring_size, bool use_bus_addr);
......
...@@ -183,11 +183,12 @@ static void cik_ih_irq_disable(struct amdgpu_device *adev) ...@@ -183,11 +183,12 @@ static void cik_ih_irq_disable(struct amdgpu_device *adev)
* Used by cik_irq_process(). * Used by cik_irq_process().
* Returns the value of the wptr. * Returns the value of the wptr.
*/ */
static u32 cik_ih_get_wptr(struct amdgpu_device *adev) static u32 cik_ih_get_wptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
u32 wptr, tmp; u32 wptr, tmp;
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);
if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) {
wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK; wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
...@@ -196,13 +197,13 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev) ...@@ -196,13 +197,13 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
* this should allow us to catchup. * this should allow us to catchup.
*/ */
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask); wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask; ih->rptr = (wptr + 16) & ih->ptr_mask;
tmp = RREG32(mmIH_RB_CNTL); tmp = RREG32(mmIH_RB_CNTL);
tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
WREG32(mmIH_RB_CNTL, tmp); WREG32(mmIH_RB_CNTL, tmp);
} }
return (wptr & adev->irq.ih.ptr_mask); return (wptr & ih->ptr_mask);
} }
/* CIK IV Ring /* CIK IV Ring
...@@ -237,16 +238,17 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev) ...@@ -237,16 +238,17 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
* position and also advance the position. * position and also advance the position.
*/ */
static void cik_ih_decode_iv(struct amdgpu_device *adev, static void cik_ih_decode_iv(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih,
struct amdgpu_iv_entry *entry) struct amdgpu_iv_entry *entry)
{ {
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
u32 ring_index = adev->irq.ih.rptr >> 2; u32 ring_index = ih->rptr >> 2;
uint32_t dw[4]; uint32_t dw[4];
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY; entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
entry->src_id = dw[0] & 0xff; entry->src_id = dw[0] & 0xff;
...@@ -256,7 +258,7 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev, ...@@ -256,7 +258,7 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
entry->pasid = (dw[2] >> 16) & 0xffff; entry->pasid = (dw[2] >> 16) & 0xffff;
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
adev->irq.ih.rptr += 16; ih->rptr += 16;
} }
/** /**
...@@ -266,9 +268,10 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev, ...@@ -266,9 +268,10 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
* *
* Set the IH ring buffer rptr. * Set the IH ring buffer rptr.
*/ */
static void cik_ih_set_rptr(struct amdgpu_device *adev) static void cik_ih_set_rptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr); WREG32(mmIH_RB_RPTR, ih->rptr);
} }
static int cik_ih_early_init(void *handle) static int cik_ih_early_init(void *handle)
......
...@@ -185,11 +185,12 @@ static void cz_ih_irq_disable(struct amdgpu_device *adev) ...@@ -185,11 +185,12 @@ static void cz_ih_irq_disable(struct amdgpu_device *adev)
* Used by cz_irq_process(VI). * Used by cz_irq_process(VI).
* Returns the value of the wptr. * Returns the value of the wptr.
*/ */
static u32 cz_ih_get_wptr(struct amdgpu_device *adev) static u32 cz_ih_get_wptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
u32 wptr, tmp; u32 wptr, tmp;
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
...@@ -198,13 +199,13 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev) ...@@ -198,13 +199,13 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
* this should allow us to catchup. * this should allow us to catchup.
*/ */
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask); wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask; ih->rptr = (wptr + 16) & ih->ptr_mask;
tmp = RREG32(mmIH_RB_CNTL); tmp = RREG32(mmIH_RB_CNTL);
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
WREG32(mmIH_RB_CNTL, tmp); WREG32(mmIH_RB_CNTL, tmp);
} }
return (wptr & adev->irq.ih.ptr_mask); return (wptr & ih->ptr_mask);
} }
/** /**
...@@ -216,16 +217,17 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev) ...@@ -216,16 +217,17 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
* position and also advance the position. * position and also advance the position.
*/ */
static void cz_ih_decode_iv(struct amdgpu_device *adev, static void cz_ih_decode_iv(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry) struct amdgpu_ih_ring *ih,
struct amdgpu_iv_entry *entry)
{ {
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
u32 ring_index = adev->irq.ih.rptr >> 2; u32 ring_index = ih->rptr >> 2;
uint32_t dw[4]; uint32_t dw[4];
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY; entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
entry->src_id = dw[0] & 0xff; entry->src_id = dw[0] & 0xff;
...@@ -235,7 +237,7 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev, ...@@ -235,7 +237,7 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
entry->pasid = (dw[2] >> 16) & 0xffff; entry->pasid = (dw[2] >> 16) & 0xffff;
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
adev->irq.ih.rptr += 16; ih->rptr += 16;
} }
/** /**
...@@ -245,9 +247,10 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev, ...@@ -245,9 +247,10 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
* *
* Set the IH ring buffer rptr. * Set the IH ring buffer rptr.
*/ */
static void cz_ih_set_rptr(struct amdgpu_device *adev) static void cz_ih_set_rptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr); WREG32(mmIH_RB_RPTR, ih->rptr);
} }
static int cz_ih_early_init(void *handle) static int cz_ih_early_init(void *handle)
......
...@@ -185,11 +185,12 @@ static void iceland_ih_irq_disable(struct amdgpu_device *adev) ...@@ -185,11 +185,12 @@ static void iceland_ih_irq_disable(struct amdgpu_device *adev)
* Used by cz_irq_process(VI). * Used by cz_irq_process(VI).
* Returns the value of the wptr. * Returns the value of the wptr.
*/ */
static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) static u32 iceland_ih_get_wptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
u32 wptr, tmp; u32 wptr, tmp;
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
...@@ -198,13 +199,13 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) ...@@ -198,13 +199,13 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
* this should allow us to catchup. * this should allow us to catchup.
*/ */
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask); wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask; ih->rptr = (wptr + 16) & ih->ptr_mask;
tmp = RREG32(mmIH_RB_CNTL); tmp = RREG32(mmIH_RB_CNTL);
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
WREG32(mmIH_RB_CNTL, tmp); WREG32(mmIH_RB_CNTL, tmp);
} }
return (wptr & adev->irq.ih.ptr_mask); return (wptr & ih->ptr_mask);
} }
/** /**
...@@ -216,16 +217,17 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) ...@@ -216,16 +217,17 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
* position and also advance the position. * position and also advance the position.
*/ */
static void iceland_ih_decode_iv(struct amdgpu_device *adev, static void iceland_ih_decode_iv(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih,
struct amdgpu_iv_entry *entry) struct amdgpu_iv_entry *entry)
{ {
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
u32 ring_index = adev->irq.ih.rptr >> 2; u32 ring_index = ih->rptr >> 2;
uint32_t dw[4]; uint32_t dw[4];
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY; entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
entry->src_id = dw[0] & 0xff; entry->src_id = dw[0] & 0xff;
...@@ -235,7 +237,7 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev, ...@@ -235,7 +237,7 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
entry->pasid = (dw[2] >> 16) & 0xffff; entry->pasid = (dw[2] >> 16) & 0xffff;
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
adev->irq.ih.rptr += 16; ih->rptr += 16;
} }
/** /**
...@@ -245,9 +247,10 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev, ...@@ -245,9 +247,10 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
* *
* Set the IH ring buffer rptr. * Set the IH ring buffer rptr.
*/ */
static void iceland_ih_set_rptr(struct amdgpu_device *adev) static void iceland_ih_set_rptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr); WREG32(mmIH_RB_RPTR, ih->rptr);
} }
static int iceland_ih_early_init(void *handle) static int iceland_ih_early_init(void *handle)
......
...@@ -100,34 +100,36 @@ static void si_ih_irq_disable(struct amdgpu_device *adev) ...@@ -100,34 +100,36 @@ static void si_ih_irq_disable(struct amdgpu_device *adev)
mdelay(1); mdelay(1);
} }
static u32 si_ih_get_wptr(struct amdgpu_device *adev) static u32 si_ih_get_wptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
u32 wptr, tmp; u32 wptr, tmp;
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);
if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) {
wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK; wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask); wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask; ih->rptr = (wptr + 16) & ih->ptr_mask;
tmp = RREG32(IH_RB_CNTL); tmp = RREG32(IH_RB_CNTL);
tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
WREG32(IH_RB_CNTL, tmp); WREG32(IH_RB_CNTL, tmp);
} }
return (wptr & adev->irq.ih.ptr_mask); return (wptr & ih->ptr_mask);
} }
static void si_ih_decode_iv(struct amdgpu_device *adev, static void si_ih_decode_iv(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry) struct amdgpu_ih_ring *ih,
struct amdgpu_iv_entry *entry)
{ {
u32 ring_index = adev->irq.ih.rptr >> 2; u32 ring_index = ih->rptr >> 2;
uint32_t dw[4]; uint32_t dw[4];
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY; entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
entry->src_id = dw[0] & 0xff; entry->src_id = dw[0] & 0xff;
...@@ -135,12 +137,13 @@ static void si_ih_decode_iv(struct amdgpu_device *adev, ...@@ -135,12 +137,13 @@ static void si_ih_decode_iv(struct amdgpu_device *adev,
entry->ring_id = dw[2] & 0xff; entry->ring_id = dw[2] & 0xff;
entry->vmid = (dw[2] >> 8) & 0xff; entry->vmid = (dw[2] >> 8) & 0xff;
adev->irq.ih.rptr += 16; ih->rptr += 16;
} }
static void si_ih_set_rptr(struct amdgpu_device *adev) static void si_ih_set_rptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
WREG32(IH_RB_RPTR, adev->irq.ih.rptr); WREG32(IH_RB_RPTR, ih->rptr);
} }
static int si_ih_early_init(void *handle) static int si_ih_early_init(void *handle)
......
...@@ -193,14 +193,15 @@ static void tonga_ih_irq_disable(struct amdgpu_device *adev) ...@@ -193,14 +193,15 @@ static void tonga_ih_irq_disable(struct amdgpu_device *adev)
* Used by cz_irq_process(VI). * Used by cz_irq_process(VI).
* Returns the value of the wptr. * Returns the value of the wptr.
*/ */
static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) static u32 tonga_ih_get_wptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
u32 wptr, tmp; u32 wptr, tmp;
if (adev->irq.ih.use_bus_addr) if (adev->irq.ih.use_bus_addr)
wptr = le32_to_cpu(adev->irq.ih.ring[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(ih->ring[ih->wptr_offs]);
else else
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
...@@ -209,13 +210,13 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) ...@@ -209,13 +210,13 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
* this should allow us to catchup. * this should allow us to catchup.
*/ */
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask); wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask; ih->rptr = (wptr + 16) & ih->ptr_mask;
tmp = RREG32(mmIH_RB_CNTL); tmp = RREG32(mmIH_RB_CNTL);
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
WREG32(mmIH_RB_CNTL, tmp); WREG32(mmIH_RB_CNTL, tmp);
} }
return (wptr & adev->irq.ih.ptr_mask); return (wptr & ih->ptr_mask);
} }
/** /**
...@@ -227,16 +228,17 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) ...@@ -227,16 +228,17 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
* position and also advance the position. * position and also advance the position.
*/ */
static void tonga_ih_decode_iv(struct amdgpu_device *adev, static void tonga_ih_decode_iv(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry) struct amdgpu_ih_ring *ih,
struct amdgpu_iv_entry *entry)
{ {
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
u32 ring_index = adev->irq.ih.rptr >> 2; u32 ring_index = ih->rptr >> 2;
uint32_t dw[4]; uint32_t dw[4];
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY; entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
entry->src_id = dw[0] & 0xff; entry->src_id = dw[0] & 0xff;
...@@ -246,7 +248,7 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev, ...@@ -246,7 +248,7 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev,
entry->pasid = (dw[2] >> 16) & 0xffff; entry->pasid = (dw[2] >> 16) & 0xffff;
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
adev->irq.ih.rptr += 16; ih->rptr += 16;
} }
/** /**
...@@ -256,17 +258,18 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev, ...@@ -256,17 +258,18 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev,
* *
* Set the IH ring buffer rptr. * Set the IH ring buffer rptr.
*/ */
static void tonga_ih_set_rptr(struct amdgpu_device *adev) static void tonga_ih_set_rptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
if (adev->irq.ih.use_doorbell) { if (ih->use_doorbell) {
/* XXX check if swapping is necessary on BE */ /* XXX check if swapping is necessary on BE */
if (adev->irq.ih.use_bus_addr) if (ih->use_bus_addr)
adev->irq.ih.ring[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr; ih->ring[ih->rptr_offs] = ih->rptr;
else else
adev->wb.wb[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr; adev->wb.wb[ih->rptr_offs] = ih->rptr;
WDOORBELL32(adev->irq.ih.doorbell_index, adev->irq.ih.rptr); WDOORBELL32(ih->doorbell_index, ih->rptr);
} else { } else {
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr); WREG32(mmIH_RB_RPTR, ih->rptr);
} }
} }
......
...@@ -191,14 +191,15 @@ static void vega10_ih_irq_disable(struct amdgpu_device *adev) ...@@ -191,14 +191,15 @@ static void vega10_ih_irq_disable(struct amdgpu_device *adev)
* ring buffer overflow and deal with it. * ring buffer overflow and deal with it.
* Returns the value of the wptr. * Returns the value of the wptr.
*/ */
static u32 vega10_ih_get_wptr(struct amdgpu_device *adev) static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
u32 wptr, tmp; u32 wptr, tmp;
if (adev->irq.ih.use_bus_addr) if (ih->use_bus_addr)
wptr = le32_to_cpu(adev->irq.ih.ring[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(ih->ring[ih->wptr_offs]);
else else
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]); wptr = le32_to_cpu(adev->wb.wb[ih->wptr_offs]);
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) { if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0); wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
...@@ -207,16 +208,16 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev) ...@@ -207,16 +208,16 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev)
* from the last not overwritten vector (wptr + 32). Hopefully * from the last not overwritten vector (wptr + 32). Hopefully
* this should allow us to catchup. * this should allow us to catchup.
*/ */
tmp = (wptr + 32) & adev->irq.ih.ptr_mask; tmp = (wptr + 32) & ih->ptr_mask;
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
wptr, adev->irq.ih.rptr, tmp); wptr, ih->rptr, tmp);
adev->irq.ih.rptr = tmp; ih->rptr = tmp;
tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL)); tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL));
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
WREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL), tmp); WREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL), tmp);
} }
return (wptr & adev->irq.ih.ptr_mask); return (wptr & ih->ptr_mask);
} }
/** /**
...@@ -228,20 +229,21 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev) ...@@ -228,20 +229,21 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev)
* position and also advance the position. * position and also advance the position.
*/ */
static void vega10_ih_decode_iv(struct amdgpu_device *adev, static void vega10_ih_decode_iv(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry) struct amdgpu_ih_ring *ih,
struct amdgpu_iv_entry *entry)
{ {
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
u32 ring_index = adev->irq.ih.rptr >> 2; u32 ring_index = ih->rptr >> 2;
uint32_t dw[8]; uint32_t dw[8];
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]); dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]); dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
dw[4] = le32_to_cpu(adev->irq.ih.ring[ring_index + 4]); dw[4] = le32_to_cpu(ih->ring[ring_index + 4]);
dw[5] = le32_to_cpu(adev->irq.ih.ring[ring_index + 5]); dw[5] = le32_to_cpu(ih->ring[ring_index + 5]);
dw[6] = le32_to_cpu(adev->irq.ih.ring[ring_index + 6]); dw[6] = le32_to_cpu(ih->ring[ring_index + 6]);
dw[7] = le32_to_cpu(adev->irq.ih.ring[ring_index + 7]); dw[7] = le32_to_cpu(ih->ring[ring_index + 7]);
entry->client_id = dw[0] & 0xff; entry->client_id = dw[0] & 0xff;
entry->src_id = (dw[0] >> 8) & 0xff; entry->src_id = (dw[0] >> 8) & 0xff;
...@@ -257,9 +259,8 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev, ...@@ -257,9 +259,8 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
entry->src_data[2] = dw[6]; entry->src_data[2] = dw[6];
entry->src_data[3] = dw[7]; entry->src_data[3] = dw[7];
/* wptr/rptr are in bytes! */ /* wptr/rptr are in bytes! */
adev->irq.ih.rptr += 32; ih->rptr += 32;
} }
/** /**
...@@ -269,17 +270,18 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev, ...@@ -269,17 +270,18 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
* *
* Set the IH ring buffer rptr. * Set the IH ring buffer rptr.
*/ */
static void vega10_ih_set_rptr(struct amdgpu_device *adev) static void vega10_ih_set_rptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{ {
if (adev->irq.ih.use_doorbell) { if (ih->use_doorbell) {
/* XXX check if swapping is necessary on BE */ /* XXX check if swapping is necessary on BE */
if (adev->irq.ih.use_bus_addr) if (ih->use_bus_addr)
adev->irq.ih.ring[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr; ih->ring[ih->rptr_offs] = ih->rptr;
else else
adev->wb.wb[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr; adev->wb.wb[ih->rptr_offs] = ih->rptr;
WDOORBELL32(adev->irq.ih.doorbell_index, adev->irq.ih.rptr); WDOORBELL32(ih->doorbell_index, ih->rptr);
} else { } else {
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, adev->irq.ih.rptr); WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment