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

Commit 1c949842 authored by Dave Airlie's avatar Dave Airlie Committed by Alex Deucher
Browse files

drm/radeon: add locking around atombios scratch space usage



While developing MST support I noticed I often got the wrong data
back from a transaction, in a racy fashion. I noticed the scratch
space wasn't locked against concurrent users.

Based on a patch by Alex, but I've made it a bit more obvious when
things are locked.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent 03dca708
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1217,7 +1217,7 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32
	return ret;
}

int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
int atom_execute_table_scratch_unlocked(struct atom_context *ctx, int index, uint32_t * params)
{
	int r;

@@ -1238,6 +1238,15 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
	return r;
}

int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
{
	int r;
	mutex_lock(&ctx->scratch_mutex);
	r = atom_execute_table_scratch_unlocked(ctx, index, params);
	mutex_unlock(&ctx->scratch_mutex);
	return r;
}

static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };

static void atom_index_iio(struct atom_context *ctx, int base)
+2 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ struct card_info {
struct atom_context {
	struct card_info *card;
	struct mutex mutex;
	struct mutex scratch_mutex;
	void *bios;
	uint32_t cmd_table, data_table;
	uint16_t *iio;
@@ -145,6 +146,7 @@ extern int atom_debug;

struct atom_context *atom_parse(struct card_info *, void *);
int atom_execute_table(struct atom_context *, int, uint32_t *);
int atom_execute_table_scratch_unlocked(struct atom_context *, int, uint32_t *);
int atom_asic_init(struct atom_context *);
void atom_destroy(struct atom_context *);
bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
+3 −1
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ 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);

	base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);

@@ -113,7 +114,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
	if (ASIC_IS_DCE4(rdev))
		args.v2.ucHPD_ID = chan->rec.hpd;

	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
	atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);

	*ack = args.v1.ucReplyStatus;

@@ -147,6 +148,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,

	r = recv_bytes;
done:
	mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
	mutex_unlock(&chan->mutex);

	return r;
+3 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ 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);

	base = (unsigned char *)rdev->mode_info.atom_context->scratch;

@@ -82,7 +83,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
	args.ucSlaveAddr = slave_addr << 1;
	args.ucLineNumber = chan->rec.i2c_id;

	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
	atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);

	/* error */
	if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {
@@ -95,6 +96,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
		radeon_atom_copy_swap(buf, base, num, false);

done:
	mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
	mutex_unlock(&chan->mutex);

	return r;
+1 −0
Original line number Diff line number Diff line
@@ -952,6 +952,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
	}

	mutex_init(&rdev->mode_info.atom_context->mutex);
	mutex_init(&rdev->mode_info.atom_context->scratch_mutex);
	radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
	atom_allocate_fb_scratch(rdev->mode_info.atom_context);
	return 0;