From: Dave Airlie <airl...@redhat.com>

This adds support to process short HPD irqs on SI gpus.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 drivers/gpu/drm/radeon/si.c | 100 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 88 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 73107fe..a928283 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -6051,12 +6051,12 @@ int si_irq_set(struct radeon_device *rdev)
                (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);

        if (!ASIC_IS_NODCE(rdev)) {
-               hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
-               hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
-               hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
-               hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
-               hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
-               hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+               hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | 
DC_HPDx_RX_INT_EN);
+               hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | 
DC_HPDx_RX_INT_EN);
+               hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | 
DC_HPDx_RX_INT_EN);
+               hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | 
DC_HPDx_RX_INT_EN);
+               hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | 
DC_HPDx_RX_INT_EN);
+               hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | 
DC_HPDx_RX_INT_EN);
        }

        dma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
@@ -6119,27 +6119,27 @@ int si_irq_set(struct radeon_device *rdev)
        }
        if (rdev->irq.hpd[0]) {
                DRM_DEBUG("si_irq_set: hpd 1\n");
-               hpd1 |= DC_HPDx_INT_EN;
+               hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
        }
        if (rdev->irq.hpd[1]) {
                DRM_DEBUG("si_irq_set: hpd 2\n");
-               hpd2 |= DC_HPDx_INT_EN;
+               hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
        }
        if (rdev->irq.hpd[2]) {
                DRM_DEBUG("si_irq_set: hpd 3\n");
-               hpd3 |= DC_HPDx_INT_EN;
+               hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
        }
        if (rdev->irq.hpd[3]) {
                DRM_DEBUG("si_irq_set: hpd 4\n");
-               hpd4 |= DC_HPDx_INT_EN;
+               hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
        }
        if (rdev->irq.hpd[4]) {
                DRM_DEBUG("si_irq_set: hpd 5\n");
-               hpd5 |= DC_HPDx_INT_EN;
+               hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
        }
        if (rdev->irq.hpd[5]) {
                DRM_DEBUG("si_irq_set: hpd 6\n");
-               hpd6 |= DC_HPDx_INT_EN;
+               hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
        }

        WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
@@ -6299,6 +6299,37 @@ static inline void si_irq_ack(struct radeon_device *rdev)
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
+
+       if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
+               tmp = RREG32(DC_HPD1_INT_CONTROL);
+               tmp |= DC_HPDx_RX_INT_ACK;
+               WREG32(DC_HPD1_INT_CONTROL, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) 
{
+               tmp = RREG32(DC_HPD2_INT_CONTROL);
+               tmp |= DC_HPDx_RX_INT_ACK;
+               WREG32(DC_HPD2_INT_CONTROL, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & 
DC_HPD3_RX_INTERRUPT) {
+               tmp = RREG32(DC_HPD3_INT_CONTROL);
+               tmp |= DC_HPDx_RX_INT_ACK;
+               WREG32(DC_HPD3_INT_CONTROL, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & 
DC_HPD4_RX_INTERRUPT) {
+               tmp = RREG32(DC_HPD4_INT_CONTROL);
+               tmp |= DC_HPDx_RX_INT_ACK;
+               WREG32(DC_HPD4_INT_CONTROL, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & 
DC_HPD5_RX_INTERRUPT) {
+               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp |= DC_HPDx_RX_INT_ACK;
+               WREG32(DC_HPD5_INT_CONTROL, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & 
DC_HPD6_RX_INTERRUPT) {
+               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp |= DC_HPDx_RX_INT_ACK;
+               WREG32(DC_HPD6_INT_CONTROL, tmp);
+       }
 }

 static void si_irq_disable(struct radeon_device *rdev)
@@ -6364,6 +6395,7 @@ int si_irq_process(struct radeon_device *rdev)
        u32 src_id, src_data, ring_id;
        u32 ring_index;
        bool queue_hotplug = false;
+       bool queue_dp = false;
        bool queue_thermal = false;
        u32 status, addr;

@@ -6604,6 +6636,48 @@ restart_ih:
                                        DRM_DEBUG("IH: HPD6\n");
                                }
                                break;
+                       case 6:
+                               if (rdev->irq.stat_regs.evergreen.disp_int & 
DC_HPD1_RX_INTERRUPT) {
+                                       rdev->irq.stat_regs.evergreen.disp_int 
&= ~DC_HPD1_RX_INTERRUPT;
+                                       queue_dp = true;
+                                       DRM_DEBUG("IH: HPD_RX 1\n");
+                               }
+                               break;
+                       case 7:
+                               if (rdev->irq.stat_regs.evergreen.disp_int_cont 
& DC_HPD2_RX_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
+                                       queue_dp = true;
+                                       DRM_DEBUG("IH: HPD_RX 2\n");
+                               }
+                               break;
+                       case 8:
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
+                                       queue_dp = true;
+                                       DRM_DEBUG("IH: HPD_RX 3\n");
+                               }
+                               break;
+                       case 9:
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
+                                       queue_dp = true;
+                                       DRM_DEBUG("IH: HPD_RX 4\n");
+                               }
+                               break;
+                       case 10:
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
+                                       queue_dp = true;
+                                       DRM_DEBUG("IH: HPD_RX 5\n");
+                               }
+                               break;
+                       case 11:
+                               if 
(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
+                                       
rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
+                                       queue_dp = true;
+                                       DRM_DEBUG("IH: HPD_RX 6\n");
+                               }
+                               break;
                        default:
                                DRM_DEBUG("Unhandled interrupt: %d %d\n", 
src_id, src_data);
                                break;
@@ -6682,6 +6756,8 @@ restart_ih:
                rptr &= rdev->ih.ptr_mask;
                WREG32(IH_RB_RPTR, rptr);
        }
+       if (queue_dp)
+               schedule_work(&rdev->dp_work);
        if (queue_hotplug)
                schedule_work(&rdev->hotplug_work);
        if (queue_thermal && rdev->pm.dpm_enabled)
-- 
2.1.0

Reply via email to