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

Commit 0a5b7b0b authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/radeon: add spinlocks for indirect register accesss



This adds spinlocks to protect access to other
indirect register apertures.  These indirect spaces are
used pretty infrequently and we haven't had an reported
problems, but better safe than sorry.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent fe78118c
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -122,20 +122,27 @@ int kv_get_temp(struct radeon_device *rdev)
 */
u32 cik_pciep_rreg(struct radeon_device *rdev, u32 reg)
{
	unsigned long flags;
	u32 r;

	spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
	WREG32(PCIE_INDEX, reg);
	(void)RREG32(PCIE_INDEX);
	r = RREG32(PCIE_DATA);
	spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
	return r;
}

void cik_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
	WREG32(PCIE_INDEX, reg);
	(void)RREG32(PCIE_INDEX);
	WREG32(PCIE_DATA, v);
	(void)RREG32(PCIE_DATA);
	spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
}

static const u32 spectre_rlc_save_restore_register_list[] =
+8 −0
Original line number Diff line number Diff line
@@ -28,22 +28,30 @@
static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
			      u32 block_offset, u32 reg)
{
	unsigned long flags;
	u32 r;

	spin_lock_irqsave(&rdev->end_idx_lock, flags);
	WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
	r = RREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset);
	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);

	return r;
}

static void dce6_endpoint_wreg(struct radeon_device *rdev,
			       u32 block_offset, u32 reg, u32 v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->end_idx_lock, flags);
	if (ASIC_IS_DCE8(rdev))
		WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
	else
		WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset,
		       AZ_ENDPOINT_REG_WRITE_EN | AZ_ENDPOINT_REG_INDEX(reg));
	WREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset, v);
	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
}

#define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg))
+7 −0
Original line number Diff line number Diff line
@@ -2853,21 +2853,28 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev)

uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg)
{
	unsigned long flags;
	uint32_t data;

	spin_lock_irqsave(&rdev->pll_idx_lock, flags);
	WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f);
	r100_pll_errata_after_index(rdev);
	data = RREG32(RADEON_CLOCK_CNTL_DATA);
	r100_pll_errata_after_data(rdev);
	spin_unlock_irqrestore(&rdev->pll_idx_lock, flags);
	return data;
}

void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->pll_idx_lock, flags);
	WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN));
	r100_pll_errata_after_index(rdev);
	WREG32(RADEON_CLOCK_CNTL_DATA, v);
	r100_pll_errata_after_data(rdev);
	spin_unlock_irqrestore(&rdev->pll_idx_lock, flags);
}

static void r100_set_safe_registers(struct radeon_device *rdev)
+7 −0
Original line number Diff line number Diff line
@@ -160,18 +160,25 @@ void r420_pipes_init(struct radeon_device *rdev)

u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg)
{
	unsigned long flags;
	u32 r;

	spin_lock_irqsave(&rdev->mc_idx_lock, flags);
	WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg));
	r = RREG32(R_0001FC_MC_IND_DATA);
	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
	return r;
}

void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->mc_idx_lock, flags);
	WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) |
		S_0001F8_MC_IND_WR_EN(1));
	WREG32(R_0001FC_MC_IND_DATA, v);
	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
}

static void r420_debugfs(struct radeon_device *rdev)
+14 −0
Original line number Diff line number Diff line
@@ -1045,20 +1045,27 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev)

uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg)
{
	unsigned long flags;
	uint32_t r;

	spin_lock_irqsave(&rdev->mc_idx_lock, flags);
	WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg));
	r = RREG32(R_0028FC_MC_DATA);
	WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR);
	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
	return r;
}

void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->mc_idx_lock, flags);
	WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) |
		S_0028F8_MC_IND_WR_EN(1));
	WREG32(R_0028FC_MC_DATA, v);
	WREG32(R_0028F8_MC_INDEX, 0x7F);
	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
}

static void r600_mc_program(struct radeon_device *rdev)
@@ -2092,20 +2099,27 @@ static void r600_gpu_init(struct radeon_device *rdev)
 */
u32 r600_pciep_rreg(struct radeon_device *rdev, u32 reg)
{
	unsigned long flags;
	u32 r;

	spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
	WREG32(PCIE_PORT_INDEX, ((reg) & 0xff));
	(void)RREG32(PCIE_PORT_INDEX);
	r = RREG32(PCIE_PORT_DATA);
	spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
	return r;
}

void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
	WREG32(PCIE_PORT_INDEX, ((reg) & 0xff));
	(void)RREG32(PCIE_PORT_INDEX);
	WREG32(PCIE_PORT_DATA, (v));
	(void)RREG32(PCIE_PORT_DATA);
	spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
}

/*
Loading