From 7979bc7d4ee00d05960bceed35d929de28683cef Mon Sep 17 00:00:00 2001
From: Alex Deucher <alexander.deucher@amd.com>
Date: Mon, 10 Nov 2014 11:32:42 -0500
Subject: [PATCH] drm/radeon: protect atom scratch buffer with a mutex
There is just one scratch buffer, but it can be used
by multiple atom clients.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/radeon/atom.c | 4 ++++
drivers/gpu/drm/radeon/atom.h | 2 ++
drivers/gpu/drm/radeon/atombios_dp.c | 4 ++++
drivers/gpu/drm/radeon/atombios_i2c.c | 4 ++++
drivers/gpu/drm/radeon/radeon_device.c | 1 +
5 files changed, 15 insertions(+)
@@ -1221,6 +1221,8 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
{
int r;
+ if (ctx->driver_uses_scratch == false)
+ mutex_lock(&ctx->scratch_mutex);
mutex_lock(&ctx->mutex);
/* reset data block */
ctx->data_block = 0;
@@ -1234,6 +1236,8 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
ctx->divmul[0] = 0;
ctx->divmul[1] = 0;
r = atom_execute_table_locked(ctx, index, params);
+ if (ctx->driver_uses_scratch == false)
+ mutex_unlock(&ctx->scratch_mutex);
mutex_unlock(&ctx->mutex);
return r;
}
@@ -137,6 +137,8 @@ struct atom_context {
uint8_t shift;
int cs_equal, cs_above;
int io_mode;
+ struct mutex scratch_mutex;
+ bool driver_uses_scratch;
uint32_t *scratch;
int scratch_size_bytes;
};
@@ -100,6 +100,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
memset(&args, 0, sizeof(args));
mutex_lock(&chan->mutex);
+ mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);
+ rdev->mode_info.atom_context->driver_uses_scratch = true;
base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
@@ -147,6 +149,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
r = recv_bytes;
done:
+ rdev->mode_info.atom_context->driver_uses_scratch = false;
+ mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
mutex_unlock(&chan->mutex);
return r;
@@ -48,6 +48,8 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
memset(&args, 0, sizeof(args));
mutex_lock(&chan->mutex);
+ mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);
+ rdev->mode_info.atom_context->driver_uses_scratch = true;
base = (unsigned char *)rdev->mode_info.atom_context->scratch;
@@ -95,6 +97,8 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
radeon_atom_copy_swap(buf, base, num, false);
done:
+ rdev->mode_info.atom_context->driver_uses_scratch = false;
+ mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
mutex_unlock(&chan->mutex);
return r;
@@ -954,6 +954,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
mutex_init(&rdev->mode_info.atom_context->mutex);
radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
atom_allocate_fb_scratch(rdev->mode_info.atom_context);
+ mutex_init(&rdev->mode_info.atom_context->scratch_mutex);
return 0;
}
--
1.8.3.1