Skip to contentSkip to conversation

drm/radeon: add locking around atombios scratch space usage

PATCH Applied Dave Airlie 2 participants 2 messages Nov 10, 2014 – Nov 11, 2014

Subsystems (2)
lore
Share & tools
lore

Dave Airlie

author maintainer
#0 lore raw

PATCH 1/1 drm/radeon: add locking around atombios scratch space usage

From: Dave Airlie <[email protected]>

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.

---
 drivers/gpu/drm/radeon/atom.c          | 11 ++++++++++-
 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, 19 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/atom.c +10 -1
index 6f26eb7..bec41c4 100644
@@ -1218,7 +1218,7 @@ free:
 	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;
 
@@ -1239,6 +1239,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)
drivers/gpu/drm/radeon/atom.h +2 -0
index bf9e6f2..6dffe15 100644
@@ -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;
@@ -146,6 +147,7 @@ extern int atom_reg_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,
drivers/gpu/drm/radeon/atombios_dp.c +3 -1
index bd96ae7..0f39d96 100644
@@ -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;
drivers/gpu/drm/radeon/atombios_i2c.c +3 -1
index 9c570fb..4157780 100644
@@ -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;
drivers/gpu/drm/radeon/radeon_device.c +1 -0
index 0d77dce..e63c9a4 100644
@@ -950,6 +950,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;
Signature · 6 lines
1.9.3

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Applied
#1 lore raw
Quoted 10 lines · Dave Airlie

From: Dave Airlie <[email protected]>

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.

Applied to my -fixes tree.

Alex

Quoted 130 lines
---
 drivers/gpu/drm/radeon/atom.c          | 11 ++++++++++-
 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, 19 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/atom.c +10 -1
index 6f26eb7..bec41c4 100644
@@ -1218,7 +1218,7 @@ free:
        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;
 
@@ -1239,6 +1239,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)
drivers/gpu/drm/radeon/atom.h +2 -0
index bf9e6f2..6dffe15 100644
@@ -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;
@@ -146,6 +147,7 @@ extern int atom_reg_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,
drivers/gpu/drm/radeon/atombios_dp.c +3 -1
index bd96ae7..0f39d96 100644
@@ -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;
drivers/gpu/drm/radeon/atombios_i2c.c +3 -1
index 9c570fb..4157780 100644
@@ -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;
drivers/gpu/drm/radeon/radeon_device.c +1 -1
index 0d77dce..e63c9a4 100644
@@ -950,6 +950,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;
--

1.9.3

Quoted 4 lines

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel