aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2018-02-20 08:01:18 -0500
committerHeiko Stuebner <heiko@sntech.de>2018-03-14 09:02:05 -0400
commit5f9e93fed4d45e9a8f84728aff1a8f2ab8922902 (patch)
treee927501cc748b896159558c7be94e56ec56dc630
parentce31ddd5c40c0662ffb9957b868fbd58f6eac5b3 (diff)
drm/rockchip: Clear all interrupts before requesting the IRQ
Calling request_irq() followed by disable_irq() is usually a bad idea, specially if the interrupt can be pending, and you're not yet in a position to handle it. This is exactly what happens on my kevin system when rebooting in a second kernel using kexec: Some interrupt is left pending from the previous kernel, and we take it too early, before disable_irq() could do anything. Let's clear the pending interrupts as we initialize the HW, and move the interrupt request after that point. This ensures that we're in a sane state when the interrupt is requested. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> [adapted to recent rockchip-drm changes] Signed-off-by: Heiko Stuebner <heiko@sntech.de> Link: https://patchwork.freedesktop.org/patch/msgid/20180220130120.5254-2-marc.zyngier@arm.com
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index b601c59e76a8..7a1de09d45d8 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1401,6 +1401,9 @@ static int vop_initial(struct vop *vop)
1401 usleep_range(10, 20); 1401 usleep_range(10, 20);
1402 reset_control_deassert(ahb_rst); 1402 reset_control_deassert(ahb_rst);
1403 1403
1404 VOP_INTR_SET_TYPE(vop, clear, INTR_MASK, 1);
1405 VOP_INTR_SET_TYPE(vop, enable, INTR_MASK, 0);
1406
1404 memcpy(vop->regsbak, vop->regs, vop->len); 1407 memcpy(vop->regsbak, vop->regs, vop->len);
1405 1408
1406 VOP_REG_SET(vop, misc, global_regdone_en, 1); 1409 VOP_REG_SET(vop, misc, global_regdone_en, 1);
@@ -1564,17 +1567,9 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
1564 spin_lock_init(&vop->irq_lock); 1567 spin_lock_init(&vop->irq_lock);
1565 mutex_init(&vop->vop_lock); 1568 mutex_init(&vop->vop_lock);
1566 1569
1567 ret = devm_request_irq(dev, vop->irq, vop_isr,
1568 IRQF_SHARED, dev_name(dev), vop);
1569 if (ret)
1570 return ret;
1571
1572 /* IRQ is initially disabled; it gets enabled in power_on */
1573 disable_irq(vop->irq);
1574
1575 ret = vop_create_crtc(vop); 1570 ret = vop_create_crtc(vop);
1576 if (ret) 1571 if (ret)
1577 goto err_enable_irq; 1572 return ret;
1578 1573
1579 pm_runtime_enable(&pdev->dev); 1574 pm_runtime_enable(&pdev->dev);
1580 1575
@@ -1585,13 +1580,19 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
1585 goto err_disable_pm_runtime; 1580 goto err_disable_pm_runtime;
1586 } 1581 }
1587 1582
1583 ret = devm_request_irq(dev, vop->irq, vop_isr,
1584 IRQF_SHARED, dev_name(dev), vop);
1585 if (ret)
1586 goto err_disable_pm_runtime;
1587
1588 /* IRQ is initially disabled; it gets enabled in power_on */
1589 disable_irq(vop->irq);
1590
1588 return 0; 1591 return 0;
1589 1592
1590err_disable_pm_runtime: 1593err_disable_pm_runtime:
1591 pm_runtime_disable(&pdev->dev); 1594 pm_runtime_disable(&pdev->dev);
1592 vop_destroy_crtc(vop); 1595 vop_destroy_crtc(vop);
1593err_enable_irq:
1594 enable_irq(vop->irq); /* To balance out the disable_irq above */
1595 return ret; 1596 return ret;
1596} 1597}
1597 1598