diff options
| author | Navneet Kumar <navneetk@nvidia.com> | 2017-03-28 16:50:43 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-03-30 20:34:31 -0400 |
| commit | 5fbf460eef1fecd419509bcaa5a48f39aa3ea3e0 (patch) | |
| tree | 643d7c7a9907da02fd5ac29a2cc6daf071c97fb3 | |
| parent | f12c65d844d19c4b3422609dceda748388da51c3 (diff) | |
tegra: dc: fix fake panel state machine data
In fake panel support, the state machine caches dc contexts in a 2D array. This
exposes a bug if a test switches between fake modes sequentially without falling
back to original (non fake) mode before switching to the next fake mode.
In the above scenario, coming back to the original mode (non fake) may lead to
finding no cached dc context, hence causing a crash.
go back to the old way of doing this, and have a 1D array to cache the contexts,
getting rid of the unnecessary logic/compexity from 2D array.
Bug 1883138
Change-Id: Ia3521b56b801cf00b0cc7e34047f40c8655f2cdd
Signed-off-by: Navneet Kumar <navneetk@nvidia.com>
Reviewed-on: http://git-master/r/1330141
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
| -rw-r--r-- | drivers/video/tegra/dc/dc.c | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 91fc96bb2..52508a9bd 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c | |||
| @@ -1160,8 +1160,8 @@ struct tegra_dc_out_info { | |||
| 1160 | struct tegra_edid *edid; | 1160 | struct tegra_edid *edid; |
| 1161 | }; | 1161 | }; |
| 1162 | 1162 | ||
| 1163 | static struct tegra_dc_out_info dbg_dc_out_info[TEGRA_DC_OUT_MAX] | 1163 | static struct tegra_dc_out_info dbg_dc_out_info[TEGRA_DC_OUT_MAX]; |
| 1164 | [TEGRA_DC_OUT_MAX]; | 1164 | |
| 1165 | /* array for saving the out_type for each head */ | 1165 | /* array for saving the out_type for each head */ |
| 1166 | static int boot_out_type[] = {-1, -1, -1}; | 1166 | static int boot_out_type[] = {-1, -1, -1}; |
| 1167 | 1167 | ||
| @@ -1216,7 +1216,7 @@ static int set_avdd(struct tegra_dc *dc, long cur_out, long new_out) | |||
| 1216 | */ | 1216 | */ |
| 1217 | bool is_enable = false; | 1217 | bool is_enable = false; |
| 1218 | struct tegra_dc_out *dc_out = | 1218 | struct tegra_dc_out *dc_out = |
| 1219 | &dbg_dc_out_info[boot_out_type[dc->ndev->id]][new_out].out; | 1219 | &dbg_dc_out_info[boot_out_type[dc->ndev->id]].out; |
| 1220 | 1220 | ||
| 1221 | /* cur is fake and new is fake - skip */ | 1221 | /* cur is fake and new is fake - skip */ |
| 1222 | if (is_valid_fake_support(dc, cur_out) && | 1222 | if (is_valid_fake_support(dc, cur_out) && |
| @@ -1288,37 +1288,37 @@ static ssize_t dbg_dc_out_type_set(struct file *file, | |||
| 1288 | 1288 | ||
| 1289 | /* If output is already created - save it */ | 1289 | /* If output is already created - save it */ |
| 1290 | if (dc->out_data) { | 1290 | if (dc->out_data) { |
| 1291 | dbg_dc_out_info[cur_dc_out][out_type].out_data = dc->out_data; | 1291 | dbg_dc_out_info[cur_dc_out].out_data = dc->out_data; |
| 1292 | dbg_dc_out_info[cur_dc_out][out_type].out_ops = dc->out_ops; | 1292 | dbg_dc_out_info[cur_dc_out].out_ops = dc->out_ops; |
| 1293 | memcpy(&dbg_dc_out_info[cur_dc_out][out_type].out, dc->out, | 1293 | memcpy(&dbg_dc_out_info[cur_dc_out].out, dc->out, |
| 1294 | sizeof(struct tegra_dc_out)); | 1294 | sizeof(struct tegra_dc_out)); |
| 1295 | dbg_dc_out_info[cur_dc_out][out_type].mode = dc->mode; | 1295 | dbg_dc_out_info[cur_dc_out].mode = dc->mode; |
| 1296 | dbg_dc_out_info[cur_dc_out][out_type].edid = dc->edid; | 1296 | dbg_dc_out_info[cur_dc_out].edid = dc->edid; |
| 1297 | 1297 | ||
| 1298 | if (is_valid_dsi_out(dc, cur_dc_out) && | 1298 | if (is_valid_dsi_out(dc, cur_dc_out) && |
| 1299 | dbg_dc_out_info[cur_dc_out][out_type].out_data) | 1299 | dbg_dc_out_info[cur_dc_out].out_data) |
| 1300 | tegra_dc_destroy_dsi_resources(dc, cur_dc_out); | 1300 | tegra_dc_destroy_dsi_resources(dc, cur_dc_out); |
| 1301 | 1301 | ||
| 1302 | if (!is_valid_fake_support(dc, cur_dc_out)) | 1302 | if (!is_valid_fake_support(dc, cur_dc_out)) |
| 1303 | dbg_dc_out_info[cur_dc_out][out_type].fblistindex = | 1303 | dbg_dc_out_info[cur_dc_out].fblistindex = |
| 1304 | tegra_fb_update_modelist(dc, 0); | 1304 | tegra_fb_update_modelist(dc, 0); |
| 1305 | 1305 | ||
| 1306 | set_avdd(dc, cur_dc_out, out_type); | 1306 | set_avdd(dc, cur_dc_out, out_type); |
| 1307 | } | 1307 | } |
| 1308 | 1308 | ||
| 1309 | /* If output already created - reuse it */ | 1309 | /* If output already created - reuse it */ |
| 1310 | if (dbg_dc_out_info[out_type][cur_dc_out].out_data) { | 1310 | if (dbg_dc_out_info[out_type].out_data) { |
| 1311 | mutex_lock(&dc->lp_lock); | 1311 | mutex_lock(&dc->lp_lock); |
| 1312 | mutex_lock(&dc->lock); | 1312 | mutex_lock(&dc->lock); |
| 1313 | 1313 | ||
| 1314 | /* Change the out type */ | 1314 | /* Change the out type */ |
| 1315 | dc->pdata->default_out->type = out_type; | 1315 | dc->pdata->default_out->type = out_type; |
| 1316 | dc->out_ops = dbg_dc_out_info[out_type][cur_dc_out].out_ops; | 1316 | dc->out_ops = dbg_dc_out_info[out_type].out_ops; |
| 1317 | dc->out_data = dbg_dc_out_info[out_type][cur_dc_out].out_data; | 1317 | dc->out_data = dbg_dc_out_info[out_type].out_data; |
| 1318 | memcpy(dc->out, &dbg_dc_out_info[out_type][cur_dc_out].out, | 1318 | memcpy(dc->out, &dbg_dc_out_info[out_type].out, |
| 1319 | sizeof(struct tegra_dc_out)); | 1319 | sizeof(struct tegra_dc_out)); |
| 1320 | dc->mode = dbg_dc_out_info[out_type][cur_dc_out].mode; | 1320 | dc->mode = dbg_dc_out_info[out_type].mode; |
| 1321 | dc->edid = dbg_dc_out_info[out_type][cur_dc_out].edid; | 1321 | dc->edid = dbg_dc_out_info[out_type].edid; |
| 1322 | 1322 | ||
| 1323 | /* Re-init the resources that are destroyed for dsi */ | 1323 | /* Re-init the resources that are destroyed for dsi */ |
| 1324 | if (is_valid_dsi_out(dc, out_type)) | 1324 | if (is_valid_dsi_out(dc, out_type)) |
| @@ -1326,8 +1326,7 @@ static ssize_t dbg_dc_out_type_set(struct file *file, | |||
| 1326 | 1326 | ||
| 1327 | if (!is_valid_fake_support(dc, out_type)) | 1327 | if (!is_valid_fake_support(dc, out_type)) |
| 1328 | tegra_fb_update_modelist(dc, | 1328 | tegra_fb_update_modelist(dc, |
| 1329 | dbg_dc_out_info[out_type] | 1329 | dbg_dc_out_info[out_type].fblistindex); |
| 1330 | [cur_dc_out].fblistindex); | ||
| 1331 | 1330 | ||
| 1332 | mutex_unlock(&dc->lock); | 1331 | mutex_unlock(&dc->lock); |
| 1333 | mutex_unlock(&dc->lp_lock); | 1332 | mutex_unlock(&dc->lp_lock); |
| @@ -1370,15 +1369,15 @@ static ssize_t dbg_dc_out_type_set(struct file *file, | |||
| 1370 | tegra_dc_init_fakedsi_panel(dc, out_type); | 1369 | tegra_dc_init_fakedsi_panel(dc, out_type); |
| 1371 | 1370 | ||
| 1372 | } else if (out_type == TEGRA_DC_OUT_NULL) { | 1371 | } else if (out_type == TEGRA_DC_OUT_NULL) { |
| 1373 | if (!dbg_dc_out_info[TEGRA_DC_OUT_NULL] | 1372 | if (!dbg_dc_out_info[TEGRA_DC_OUT_NULL].out_data) { |
| 1374 | [cur_dc_out].out_data) { | ||
| 1375 | allocate = true; | 1373 | allocate = true; |
| 1376 | tegra_dc_init_null_or(dc); | 1374 | tegra_dc_init_null_or(dc); |
| 1377 | } | 1375 | } |
| 1378 | } else { | 1376 | } else { |
| 1379 | /* set back to existing one */ | 1377 | /* set back to existing one */ |
| 1380 | dc->pdata->default_out->type = cur_dc_out; | 1378 | dc->pdata->default_out->type = cur_dc_out; |
| 1381 | dev_err(&dc->ndev->dev, "Unknown type is asked\n"); | 1379 | dev_err(&dc->ndev->dev, "Unknown type is asked: %ld\n", |
| 1380 | out_type); | ||
| 1382 | goto by_pass; | 1381 | goto by_pass; |
| 1383 | } | 1382 | } |
| 1384 | 1383 | ||
| @@ -1391,12 +1390,12 @@ static ssize_t dbg_dc_out_type_set(struct file *file, | |||
| 1391 | } | 1390 | } |
| 1392 | } | 1391 | } |
| 1393 | 1392 | ||
| 1394 | dbg_dc_out_info[out_type][cur_dc_out].out_ops = dc->out_ops; | 1393 | dbg_dc_out_info[out_type].out_ops = dc->out_ops; |
| 1395 | dbg_dc_out_info[out_type][cur_dc_out].out_data = dc->out_data; | 1394 | dbg_dc_out_info[out_type].out_data = dc->out_data; |
| 1396 | memcpy(&dbg_dc_out_info[out_type][cur_dc_out].out, dc->out, | 1395 | memcpy(&dbg_dc_out_info[out_type].out, dc->out, |
| 1397 | sizeof(struct tegra_dc_out)); | 1396 | sizeof(struct tegra_dc_out)); |
| 1398 | dbg_dc_out_info[out_type][cur_dc_out].mode = dc->mode; | 1397 | dbg_dc_out_info[out_type].mode = dc->mode; |
| 1399 | dbg_dc_out_info[out_type][cur_dc_out].edid = dc->edid; | 1398 | dbg_dc_out_info[out_type].edid = dc->edid; |
| 1400 | 1399 | ||
| 1401 | } | 1400 | } |
| 1402 | 1401 | ||
