From 2c385151ed6db8ded2faa3328f0377e6c5fa1e89 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 2 Dec 2012 14:06:15 +0100 Subject: [PATCH] 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 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r100.c | 13 ++++++++++++- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_device.c | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) 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); } } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 609bb18d09f1..285fb3f203af 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1556,6 +1556,8 @@ struct radeon_device { /* Register mmio */ resource_size_t rmmio_base; resource_size_t rmmio_size; + /* protects concurrent MM_INDEX/DATA based register access */ + spinlock_t mmio_idx_lock; void __iomem *rmmio; radeon_rreg_t mc_rreg; radeon_wreg_t mc_wreg; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e2f5f888c374..49b06590001e 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1059,6 +1059,7 @@ int radeon_device_init(struct radeon_device *rdev, /* Registers mapping */ /* TODO: block userspace mapping of io register */ + spin_lock_init(&rdev->mmio_idx_lock); rdev->rmmio_base = pci_resource_start(rdev->pdev, 2); rdev->rmmio_size = pci_resource_len(rdev->pdev, 2); rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size); -- GitLab