Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c385151 authored by Daniel Vetter's avatar Daniel Vetter Committed by Alex Deucher
Browse files

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: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 2ef9bdfe
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -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);
	}
}

+2 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);