aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>2007-06-21 15:23:20 -0700
committerJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>2007-06-21 15:23:20 -0700
commitafe842297f7117cf80718de78ce706f6fd83584b (patch)
treeb11b9c5e2f3647a78ceddcca60d4e8c5abfc6e94
parent741d1c80314de6f30bcc7eca7a7720b0aac3c56c (diff)
RADEON: fix race in vblank interrupt handling
It's possible that we disable vblank interrupts and clear the corresponding flag in irq_enable_reg, but receive an interrupt at just the wrong time, causing us to not ack it properly, nor report to the core kernel that it was handled. Fix that case by always handling vblank interrupts, even if the irq_enable_reg field is clear.
-rw-r--r--shared-core/radeon_irq.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c
index d1f0e313..4409026c 100644
--- a/shared-core/radeon_irq.c
+++ b/shared-core/radeon_irq.c
@@ -37,7 +37,7 @@
static void radeon_irq_set_state(drm_device_t *dev, u32 mask, int state)
{
- drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
if (state)
dev_priv->irq_enable_reg |= mask;
@@ -49,8 +49,6 @@ static void radeon_irq_set_state(drm_device_t *dev, u32 mask, int state)
int radeon_enable_vblank(drm_device_t *dev, int crtc)
{
- drm_radeon_private_t *dev_priv = dev->dev_private;
-
switch (crtc) {
case 0:
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
@@ -69,8 +67,6 @@ int radeon_enable_vblank(drm_device_t *dev, int crtc)
void radeon_disable_vblank(drm_device_t *dev, int crtc)
{
- drm_radeon_private_t *dev_priv = dev->dev_private;
-
switch (crtc) {
case 0:
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
@@ -88,7 +84,8 @@ void radeon_disable_vblank(drm_device_t *dev, int crtc)
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
u32 mask)
{
- u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+ u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
+ (mask | RADEON_CRTC_VBLANK_MASK | RADEON_CRTC2_VBLANK_MASK);
if (irqs)
RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
return irqs;