aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r100.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-12-02 14:06:15 +0100
committerAlex Deucher <alexander.deucher@amd.com>2012-12-14 10:45:23 -0500
commit2c385151ed6db8ded2faa3328f0377e6c5fa1e89 (patch)
tree3c4d37e3f7d82519964f9fb8e9224815a5d4c0f1 /drivers/gpu/drm/radeon/r100.c
parentdrm/radeon: add W|RREG32_IDX for MM_INDEX|DATA based mmio accesss (diff)
downloadlinux-dev-2c385151ed6db8ded2faa3328f0377e6c5fa1e89.tar.xz
linux-dev-2c385151ed6db8ded2faa3328f0377e6c5fa1e89.zip
drm/radeon: make indirect register access concurrency-safe
With the new per-crtc locking mutliple set-cursor calls could happen in parallel. Out of sheer paranoia I've opted for an irqsave spinlock. But if there's indeed an access from interrupt contexts to these regs it's already broken with the old code, so this can likely just be reduced to a normal spinlock. Otoh the pageflip completion happens from the vblank irq handler ... Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r--drivers/gpu/drm/radeon/r100.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index ae4c857fb173..8ff7cac222dc 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -4141,8 +4141,15 @@ uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
if (reg < rdev->rmmio_size && !always_indirect)
return readl(((void __iomem *)rdev->rmmio) + reg);
else {
+ unsigned long flags;
+ uint32_t ret;
+
+ spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
- return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+
+ return ret;
}
}
@@ -4152,8 +4159,12 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
if (reg < rdev->rmmio_size && !always_indirect)
writel(v, ((void __iomem *)rdev->rmmio) + reg);
else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
}
}