Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org

authored by

Dave Airlie and committed by
Alex Deucher
1c949842 03dca708

+19 -3
+10 -1
drivers/gpu/drm/radeon/atom.c
··· 1217 1217 return ret; 1218 1218 } 1219 1219 1220 - int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) 1220 + int atom_execute_table_scratch_unlocked(struct atom_context *ctx, int index, uint32_t * params) 1221 1221 { 1222 1222 int r; 1223 1223 ··· 1235 1235 ctx->divmul[1] = 0; 1236 1236 r = atom_execute_table_locked(ctx, index, params); 1237 1237 mutex_unlock(&ctx->mutex); 1238 + return r; 1239 + } 1240 + 1241 + int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) 1242 + { 1243 + int r; 1244 + mutex_lock(&ctx->scratch_mutex); 1245 + r = atom_execute_table_scratch_unlocked(ctx, index, params); 1246 + mutex_unlock(&ctx->scratch_mutex); 1238 1247 return r; 1239 1248 } 1240 1249
+2
drivers/gpu/drm/radeon/atom.h
··· 125 125 struct atom_context { 126 126 struct card_info *card; 127 127 struct mutex mutex; 128 + struct mutex scratch_mutex; 128 129 void *bios; 129 130 uint32_t cmd_table, data_table; 130 131 uint16_t *iio; ··· 146 145 147 146 struct atom_context *atom_parse(struct card_info *, void *); 148 147 int atom_execute_table(struct atom_context *, int, uint32_t *); 148 + int atom_execute_table_scratch_unlocked(struct atom_context *, int, uint32_t *); 149 149 int atom_asic_init(struct atom_context *); 150 150 void atom_destroy(struct atom_context *); 151 151 bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
+3 -1
drivers/gpu/drm/radeon/atombios_dp.c
··· 100 100 memset(&args, 0, sizeof(args)); 101 101 102 102 mutex_lock(&chan->mutex); 103 + mutex_lock(&rdev->mode_info.atom_context->scratch_mutex); 103 104 104 105 base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); 105 106 ··· 114 113 if (ASIC_IS_DCE4(rdev)) 115 114 args.v2.ucHPD_ID = chan->rec.hpd; 116 115 117 - atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 116 + atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args); 118 117 119 118 *ack = args.v1.ucReplyStatus; 120 119 ··· 148 147 149 148 r = recv_bytes; 150 149 done: 150 + mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex); 151 151 mutex_unlock(&chan->mutex); 152 152 153 153 return r;
+3 -1
drivers/gpu/drm/radeon/atombios_i2c.c
··· 48 48 memset(&args, 0, sizeof(args)); 49 49 50 50 mutex_lock(&chan->mutex); 51 + mutex_lock(&rdev->mode_info.atom_context->scratch_mutex); 51 52 52 53 base = (unsigned char *)rdev->mode_info.atom_context->scratch; 53 54 ··· 83 82 args.ucSlaveAddr = slave_addr << 1; 84 83 args.ucLineNumber = chan->rec.i2c_id; 85 84 86 - atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 85 + atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args); 87 86 88 87 /* error */ 89 88 if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) { ··· 96 95 radeon_atom_copy_swap(buf, base, num, false); 97 96 98 97 done: 98 + mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex); 99 99 mutex_unlock(&chan->mutex); 100 100 101 101 return r;
+1
drivers/gpu/drm/radeon/radeon_device.c
··· 952 952 } 953 953 954 954 mutex_init(&rdev->mode_info.atom_context->mutex); 955 + mutex_init(&rdev->mode_info.atom_context->scratch_mutex); 955 956 radeon_atom_initialize_bios_scratch_regs(rdev->ddev); 956 957 atom_allocate_fb_scratch(rdev->mode_info.atom_context); 957 958 return 0;