aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-10-24 07:38:21 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2016-10-25 02:32:16 -0400
commit14544d0937bf0160018a47ba74fff7fd61c22731 (patch)
treebae2d2965f80801f75d53b03c2a720f6c60c0fdb
parentc170a14e20299f600f5d5949933cf3b300fee375 (diff)
drm/edid: Only print the bad edid when aborting
Currently, if drm.debug is enabled, we get a DRM_ERROR message on the intermediate edid reads. This causes transient failures in CI which flags up the sporadic EDID read failures, which are recovered by rereading the EDID automatically. This patch combines the reporting done by drm_do_get_edid() itself with the bad block printing from get_edid_block(), into a single warning associated with the connector once all attempts to retrieve the EDID fail. v2: Print the whole EDID, marking up the bad/zero blocks. This requires recording the whole of the raw edid, then a second pass to reduce it to the valid extensions. v3: Fix invalid/valid extension fumble. References: https://bugs.freedesktop.org/show_bug.cgi?id=98228 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20161024113821.26263-1-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/drm_edid.c79
1 files changed, 56 insertions, 23 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 95de47ba1e77..9506933b41cd 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1260,6 +1260,34 @@ drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len)
1260 return ret == xfers ? 0 : -1; 1260 return ret == xfers ? 0 : -1;
1261} 1261}
1262 1262
1263static void connector_bad_edid(struct drm_connector *connector,
1264 u8 *edid, int num_blocks)
1265{
1266 int i;
1267
1268 if (connector->bad_edid_counter++ && !(drm_debug & DRM_UT_KMS))
1269 return;
1270
1271 dev_warn(connector->dev->dev,
1272 "%s: EDID is invalid:\n",
1273 connector->name);
1274 for (i = 0; i < num_blocks; i++) {
1275 u8 *block = edid + i * EDID_LENGTH;
1276 char prefix[20];
1277
1278 if (drm_edid_is_zero(block, EDID_LENGTH))
1279 sprintf(prefix, "\t[%02x] ZERO ", i);
1280 else if (!drm_edid_block_valid(block, i, false, NULL))
1281 sprintf(prefix, "\t[%02x] BAD ", i);
1282 else
1283 sprintf(prefix, "\t[%02x] GOOD ", i);
1284
1285 print_hex_dump(KERN_WARNING,
1286 prefix, DUMP_PREFIX_NONE, 16, 1,
1287 block, EDID_LENGTH, false);
1288 }
1289}
1290
1263/** 1291/**
1264 * drm_do_get_edid - get EDID data using a custom EDID block read function 1292 * drm_do_get_edid - get EDID data using a custom EDID block read function
1265 * @connector: connector we're probing 1293 * @connector: connector we're probing
@@ -1283,7 +1311,6 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
1283{ 1311{
1284 int i, j = 0, valid_extensions = 0; 1312 int i, j = 0, valid_extensions = 0;
1285 u8 *edid, *new; 1313 u8 *edid, *new;
1286 bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
1287 1314
1288 if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) 1315 if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
1289 return NULL; 1316 return NULL;
@@ -1292,7 +1319,7 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
1292 for (i = 0; i < 4; i++) { 1319 for (i = 0; i < 4; i++) {
1293 if (get_edid_block(data, edid, 0, EDID_LENGTH)) 1320 if (get_edid_block(data, edid, 0, EDID_LENGTH))
1294 goto out; 1321 goto out;
1295 if (drm_edid_block_valid(edid, 0, print_bad_edid, 1322 if (drm_edid_block_valid(edid, 0, false,
1296 &connector->edid_corrupt)) 1323 &connector->edid_corrupt))
1297 break; 1324 break;
1298 if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) { 1325 if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) {
@@ -1304,54 +1331,60 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
1304 goto carp; 1331 goto carp;
1305 1332
1306 /* if there's no extensions, we're done */ 1333 /* if there's no extensions, we're done */
1307 if (edid[0x7e] == 0) 1334 valid_extensions = edid[0x7e];
1335 if (valid_extensions == 0)
1308 return (struct edid *)edid; 1336 return (struct edid *)edid;
1309 1337
1310 new = krealloc(edid, (edid[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); 1338 new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
1311 if (!new) 1339 if (!new)
1312 goto out; 1340 goto out;
1313 edid = new; 1341 edid = new;
1314 1342
1315 for (j = 1; j <= edid[0x7e]; j++) { 1343 for (j = 1; j <= edid[0x7e]; j++) {
1316 u8 *block = edid + (valid_extensions + 1) * EDID_LENGTH; 1344 u8 *block = edid + j * EDID_LENGTH;
1317 1345
1318 for (i = 0; i < 4; i++) { 1346 for (i = 0; i < 4; i++) {
1319 if (get_edid_block(data, block, j, EDID_LENGTH)) 1347 if (get_edid_block(data, block, j, EDID_LENGTH))
1320 goto out; 1348 goto out;
1321 if (drm_edid_block_valid(block, j, 1349 if (drm_edid_block_valid(block, j, false, NULL))
1322 print_bad_edid, NULL)) {
1323 valid_extensions++;
1324 break; 1350 break;
1325 }
1326 } 1351 }
1327 1352
1328 if (i == 4 && print_bad_edid) { 1353 if (i == 4)
1329 dev_warn(connector->dev->dev, 1354 valid_extensions--;
1330 "%s: Ignoring invalid EDID block %d.\n",
1331 connector->name, j);
1332
1333 connector->bad_edid_counter++;
1334 }
1335 } 1355 }
1336 1356
1337 if (valid_extensions != edid[0x7e]) { 1357 if (valid_extensions != edid[0x7e]) {
1358 u8 *base;
1359
1360 connector_bad_edid(connector, edid, edid[0x7e] + 1);
1361
1338 edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions; 1362 edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
1339 edid[0x7e] = valid_extensions; 1363 edid[0x7e] = valid_extensions;
1340 new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); 1364
1365 new = kmalloc((valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
1341 if (!new) 1366 if (!new)
1342 goto out; 1367 goto out;
1368
1369 base = new;
1370 for (i = 0; i <= edid[0x7e]; i++) {
1371 u8 *block = edid + i * EDID_LENGTH;
1372
1373 if (!drm_edid_block_valid(block, i, false, NULL))
1374 continue;
1375
1376 memcpy(base, block, EDID_LENGTH);
1377 base += EDID_LENGTH;
1378 }
1379
1380 kfree(edid);
1343 edid = new; 1381 edid = new;
1344 } 1382 }
1345 1383
1346 return (struct edid *)edid; 1384 return (struct edid *)edid;
1347 1385
1348carp: 1386carp:
1349 if (print_bad_edid) { 1387 connector_bad_edid(connector, edid, 1);
1350 dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
1351 connector->name, j);
1352 }
1353 connector->bad_edid_counter++;
1354
1355out: 1388out:
1356 kfree(edid); 1389 kfree(edid);
1357 return NULL; 1390 return NULL;