drm/radeon: protect concurrent smc register access with a spinlock
smc registers are access indirectly via the main mmio aperture, so there may be problems with concurrent access. This adds a spinlock to protect access to this register space. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
136de91ea7
commit
fe78118c46
@ -47,10 +47,11 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
u32 smc_start_address,
|
u32 smc_start_address,
|
||||||
const u8 *src, u32 byte_count, u32 limit)
|
const u8 *src, u32 byte_count, u32 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
u32 data, original_data;
|
u32 data, original_data;
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 extra_shift;
|
u32 extra_shift;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
if (smc_start_address & 3)
|
if (smc_start_address & 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -59,13 +60,14 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
addr = smc_start_address;
|
addr = smc_start_address;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
while (byte_count >= 4) {
|
while (byte_count >= 4) {
|
||||||
/* SMC address space is BE */
|
/* SMC address space is BE */
|
||||||
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
||||||
|
|
||||||
ret = ci_set_smc_sram_address(rdev, addr, limit);
|
ret = ci_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
WREG32(SMC_IND_DATA_0, data);
|
WREG32(SMC_IND_DATA_0, data);
|
||||||
|
|
||||||
@ -80,7 +82,7 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
ret = ci_set_smc_sram_address(rdev, addr, limit);
|
ret = ci_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
original_data = RREG32(SMC_IND_DATA_0);
|
original_data = RREG32(SMC_IND_DATA_0);
|
||||||
|
|
||||||
@ -97,11 +99,15 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
ret = ci_set_smc_sram_address(rdev, addr, limit);
|
ret = ci_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
WREG32(SMC_IND_DATA_0, data);
|
WREG32(SMC_IND_DATA_0, data);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
done:
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ci_start_smc(struct radeon_device *rdev)
|
void ci_start_smc(struct radeon_device *rdev)
|
||||||
@ -197,6 +203,7 @@ PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
|
|||||||
|
|
||||||
int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
u32 ucode_start_address;
|
u32 ucode_start_address;
|
||||||
u32 ucode_size;
|
u32 ucode_size;
|
||||||
const u8 *src;
|
const u8 *src;
|
||||||
@ -219,6 +226,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
src = (const u8 *)rdev->smc_fw->data;
|
src = (const u8 *)rdev->smc_fw->data;
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
WREG32(SMC_IND_INDEX_0, ucode_start_address);
|
WREG32(SMC_IND_INDEX_0, ucode_start_address);
|
||||||
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
|
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
|
||||||
while (ucode_size >= 4) {
|
while (ucode_size >= 4) {
|
||||||
@ -231,6 +239,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
|||||||
ucode_size -= 4;
|
ucode_size -= 4;
|
||||||
}
|
}
|
||||||
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
|
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -238,25 +247,29 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
|||||||
int ci_read_smc_sram_dword(struct radeon_device *rdev,
|
int ci_read_smc_sram_dword(struct radeon_device *rdev,
|
||||||
u32 smc_address, u32 *value, u32 limit)
|
u32 smc_address, u32 *value, u32 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
ret = ci_set_smc_sram_address(rdev, smc_address, limit);
|
ret = ci_set_smc_sram_address(rdev, smc_address, limit);
|
||||||
if (ret)
|
if (ret == 0)
|
||||||
return ret;
|
*value = RREG32(SMC_IND_DATA_0);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
*value = RREG32(SMC_IND_DATA_0);
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ci_write_smc_sram_dword(struct radeon_device *rdev,
|
int ci_write_smc_sram_dword(struct radeon_device *rdev,
|
||||||
u32 smc_address, u32 value, u32 limit)
|
u32 smc_address, u32 value, u32 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
ret = ci_set_smc_sram_address(rdev, smc_address, limit);
|
ret = ci_set_smc_sram_address(rdev, smc_address, limit);
|
||||||
if (ret)
|
if (ret == 0)
|
||||||
return ret;
|
WREG32(SMC_IND_DATA_0, value);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
WREG32(SMC_IND_DATA_0, value);
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -2110,6 +2110,8 @@ struct radeon_device {
|
|||||||
resource_size_t rmmio_size;
|
resource_size_t rmmio_size;
|
||||||
/* protects concurrent MM_INDEX/DATA based register access */
|
/* protects concurrent MM_INDEX/DATA based register access */
|
||||||
spinlock_t mmio_idx_lock;
|
spinlock_t mmio_idx_lock;
|
||||||
|
/* protects concurrent SMC based register access */
|
||||||
|
spinlock_t smc_idx_lock;
|
||||||
void __iomem *rmmio;
|
void __iomem *rmmio;
|
||||||
radeon_rreg_t mc_rreg;
|
radeon_rreg_t mc_rreg;
|
||||||
radeon_wreg_t mc_wreg;
|
radeon_wreg_t mc_wreg;
|
||||||
@ -2292,17 +2294,24 @@ static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uin
|
|||||||
|
|
||||||
static inline u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
|
static inline u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
u32 r;
|
u32 r;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
||||||
r = RREG32(TN_SMC_IND_DATA_0);
|
r = RREG32(TN_SMC_IND_DATA_0);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
static inline void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
||||||
WREG32(TN_SMC_IND_DATA_0, (v));
|
WREG32(TN_SMC_IND_DATA_0, (v));
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg)
|
static inline u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg)
|
||||||
|
@ -1249,6 +1249,7 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||||||
/* Registers mapping */
|
/* Registers mapping */
|
||||||
/* TODO: block userspace mapping of io register */
|
/* TODO: block userspace mapping of io register */
|
||||||
spin_lock_init(&rdev->mmio_idx_lock);
|
spin_lock_init(&rdev->mmio_idx_lock);
|
||||||
|
spin_lock_init(&rdev->smc_idx_lock);
|
||||||
if (rdev->family >= CHIP_BONAIRE) {
|
if (rdev->family >= CHIP_BONAIRE) {
|
||||||
rdev->rmmio_base = pci_resource_start(rdev->pdev, 5);
|
rdev->rmmio_base = pci_resource_start(rdev->pdev, 5);
|
||||||
rdev->rmmio_size = pci_resource_len(rdev->pdev, 5);
|
rdev->rmmio_size = pci_resource_len(rdev->pdev, 5);
|
||||||
|
@ -274,8 +274,8 @@ static const u8 cayman_smc_int_vectors[] =
|
|||||||
0x08, 0x72, 0x08, 0x72
|
0x08, 0x72, 0x08, 0x72
|
||||||
};
|
};
|
||||||
|
|
||||||
int rv770_set_smc_sram_address(struct radeon_device *rdev,
|
static int rv770_set_smc_sram_address(struct radeon_device *rdev,
|
||||||
u16 smc_address, u16 limit)
|
u16 smc_address, u16 limit)
|
||||||
{
|
{
|
||||||
u32 addr;
|
u32 addr;
|
||||||
|
|
||||||
@ -296,9 +296,10 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
u16 smc_start_address, const u8 *src,
|
u16 smc_start_address, const u8 *src,
|
||||||
u16 byte_count, u16 limit)
|
u16 byte_count, u16 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
u32 data, original_data, extra_shift;
|
u32 data, original_data, extra_shift;
|
||||||
u16 addr;
|
u16 addr;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
if (smc_start_address & 3)
|
if (smc_start_address & 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -307,13 +308,14 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
addr = smc_start_address;
|
addr = smc_start_address;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
while (byte_count >= 4) {
|
while (byte_count >= 4) {
|
||||||
/* SMC address space is BE */
|
/* SMC address space is BE */
|
||||||
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
||||||
|
|
||||||
ret = rv770_set_smc_sram_address(rdev, addr, limit);
|
ret = rv770_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
WREG32(SMC_SRAM_DATA, data);
|
WREG32(SMC_SRAM_DATA, data);
|
||||||
|
|
||||||
@ -328,7 +330,7 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
ret = rv770_set_smc_sram_address(rdev, addr, limit);
|
ret = rv770_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
original_data = RREG32(SMC_SRAM_DATA);
|
original_data = RREG32(SMC_SRAM_DATA);
|
||||||
|
|
||||||
@ -346,12 +348,15 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
ret = rv770_set_smc_sram_address(rdev, addr, limit);
|
ret = rv770_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
WREG32(SMC_SRAM_DATA, data);
|
WREG32(SMC_SRAM_DATA, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
done:
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rv770_program_interrupt_vectors(struct radeon_device *rdev,
|
static int rv770_program_interrupt_vectors(struct radeon_device *rdev,
|
||||||
@ -461,12 +466,15 @@ PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev)
|
|||||||
|
|
||||||
static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit)
|
static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
u16 i;
|
u16 i;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
for (i = 0; i < limit; i += 4) {
|
for (i = 0; i < limit; i += 4) {
|
||||||
rv770_set_smc_sram_address(rdev, i, limit);
|
rv770_set_smc_sram_address(rdev, i, limit);
|
||||||
WREG32(SMC_SRAM_DATA, 0);
|
WREG32(SMC_SRAM_DATA, 0);
|
||||||
}
|
}
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rv770_load_smc_ucode(struct radeon_device *rdev,
|
int rv770_load_smc_ucode(struct radeon_device *rdev,
|
||||||
@ -595,27 +603,29 @@ int rv770_load_smc_ucode(struct radeon_device *rdev,
|
|||||||
int rv770_read_smc_sram_dword(struct radeon_device *rdev,
|
int rv770_read_smc_sram_dword(struct radeon_device *rdev,
|
||||||
u16 smc_address, u32 *value, u16 limit)
|
u16 smc_address, u32 *value, u16 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
|
ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
|
||||||
if (ret)
|
if (ret == 0)
|
||||||
return ret;
|
*value = RREG32(SMC_SRAM_DATA);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
*value = RREG32(SMC_SRAM_DATA);
|
return ret;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rv770_write_smc_sram_dword(struct radeon_device *rdev,
|
int rv770_write_smc_sram_dword(struct radeon_device *rdev,
|
||||||
u16 smc_address, u32 value, u16 limit)
|
u16 smc_address, u32 value, u16 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
|
ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
|
||||||
if (ret)
|
if (ret == 0)
|
||||||
return ret;
|
WREG32(SMC_SRAM_DATA, value);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
WREG32(SMC_SRAM_DATA, value);
|
return ret;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -187,8 +187,6 @@ typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE;
|
|||||||
#define RV770_SMC_SOFT_REGISTER_uvd_enabled 0x9C
|
#define RV770_SMC_SOFT_REGISTER_uvd_enabled 0x9C
|
||||||
#define RV770_SMC_SOFT_REGISTER_is_asic_lombok 0xA0
|
#define RV770_SMC_SOFT_REGISTER_is_asic_lombok 0xA0
|
||||||
|
|
||||||
int rv770_set_smc_sram_address(struct radeon_device *rdev,
|
|
||||||
u16 smc_address, u16 limit);
|
|
||||||
int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
|
int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
|
||||||
u16 smc_start_address, const u8 *src,
|
u16 smc_start_address, const u8 *src,
|
||||||
u16 byte_count, u16 limit);
|
u16 byte_count, u16 limit);
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
#include "ppsmc.h"
|
#include "ppsmc.h"
|
||||||
#include "radeon_ucode.h"
|
#include "radeon_ucode.h"
|
||||||
|
|
||||||
int si_set_smc_sram_address(struct radeon_device *rdev,
|
static int si_set_smc_sram_address(struct radeon_device *rdev,
|
||||||
u32 smc_address, u32 limit)
|
u32 smc_address, u32 limit)
|
||||||
{
|
{
|
||||||
if (smc_address & 3)
|
if (smc_address & 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -47,7 +47,8 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
u32 smc_start_address,
|
u32 smc_start_address,
|
||||||
const u8 *src, u32 byte_count, u32 limit)
|
const u8 *src, u32 byte_count, u32 limit)
|
||||||
{
|
{
|
||||||
int ret;
|
unsigned long flags;
|
||||||
|
int ret = 0;
|
||||||
u32 data, original_data, addr, extra_shift;
|
u32 data, original_data, addr, extra_shift;
|
||||||
|
|
||||||
if (smc_start_address & 3)
|
if (smc_start_address & 3)
|
||||||
@ -57,13 +58,14 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
addr = smc_start_address;
|
addr = smc_start_address;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
while (byte_count >= 4) {
|
while (byte_count >= 4) {
|
||||||
/* SMC address space is BE */
|
/* SMC address space is BE */
|
||||||
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
||||||
|
|
||||||
ret = si_set_smc_sram_address(rdev, addr, limit);
|
ret = si_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
WREG32(SMC_IND_DATA_0, data);
|
WREG32(SMC_IND_DATA_0, data);
|
||||||
|
|
||||||
@ -78,7 +80,7 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
ret = si_set_smc_sram_address(rdev, addr, limit);
|
ret = si_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
original_data = RREG32(SMC_IND_DATA_0);
|
original_data = RREG32(SMC_IND_DATA_0);
|
||||||
|
|
||||||
@ -96,11 +98,15 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
|
|||||||
|
|
||||||
ret = si_set_smc_sram_address(rdev, addr, limit);
|
ret = si_set_smc_sram_address(rdev, addr, limit);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto done;
|
||||||
|
|
||||||
WREG32(SMC_IND_DATA_0, data);
|
WREG32(SMC_IND_DATA_0, data);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
done:
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void si_start_smc(struct radeon_device *rdev)
|
void si_start_smc(struct radeon_device *rdev)
|
||||||
@ -203,6 +209,7 @@ PPSMC_Result si_wait_for_smc_inactive(struct radeon_device *rdev)
|
|||||||
|
|
||||||
int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
u32 ucode_start_address;
|
u32 ucode_start_address;
|
||||||
u32 ucode_size;
|
u32 ucode_size;
|
||||||
const u8 *src;
|
const u8 *src;
|
||||||
@ -241,6 +248,7 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
src = (const u8 *)rdev->smc_fw->data;
|
src = (const u8 *)rdev->smc_fw->data;
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
WREG32(SMC_IND_INDEX_0, ucode_start_address);
|
WREG32(SMC_IND_INDEX_0, ucode_start_address);
|
||||||
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
|
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
|
||||||
while (ucode_size >= 4) {
|
while (ucode_size >= 4) {
|
||||||
@ -253,6 +261,7 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
|||||||
ucode_size -= 4;
|
ucode_size -= 4;
|
||||||
}
|
}
|
||||||
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
|
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -260,25 +269,29 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
|
|||||||
int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
|
int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
|
||||||
u32 *value, u32 limit)
|
u32 *value, u32 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
ret = si_set_smc_sram_address(rdev, smc_address, limit);
|
ret = si_set_smc_sram_address(rdev, smc_address, limit);
|
||||||
if (ret)
|
if (ret == 0)
|
||||||
return ret;
|
*value = RREG32(SMC_IND_DATA_0);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
*value = RREG32(SMC_IND_DATA_0);
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
|
int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
|
||||||
u32 value, u32 limit)
|
u32 value, u32 limit)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||||
ret = si_set_smc_sram_address(rdev, smc_address, limit);
|
ret = si_set_smc_sram_address(rdev, smc_address, limit);
|
||||||
if (ret)
|
if (ret == 0)
|
||||||
return ret;
|
WREG32(SMC_IND_DATA_0, value);
|
||||||
|
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||||
|
|
||||||
WREG32(SMC_IND_DATA_0, value);
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user