Commit 0b2443ed authored by Jerome Glisse's avatar Jerome Glisse Committed by Dave Airlie

drm/edid: limit printk when facing bad edid

Limit printing bad edid information at one time per connector.
Connector that are connected to a bad monitor/kvm will likely
stay connected to the same bad monitor/kvm and it makes no
sense to keep printing the bad edid message.
Signed-off-by: default avatarJerome Glisse <jglisse@redhat.com>
Reviewed-by: default avatarAdam Jackson <ajax@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 09e7dcf0
...@@ -158,7 +158,7 @@ MODULE_PARM_DESC(edid_fixup, ...@@ -158,7 +158,7 @@ MODULE_PARM_DESC(edid_fixup,
* Sanity check the EDID block (base or extension). Return 0 if the block * Sanity check the EDID block (base or extension). Return 0 if the block
* doesn't check out, or 1 if it's valid. * doesn't check out, or 1 if it's valid.
*/ */
bool drm_edid_block_valid(u8 *raw_edid, int block) bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
{ {
int i; int i;
u8 csum = 0; u8 csum = 0;
...@@ -181,7 +181,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block) ...@@ -181,7 +181,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block)
for (i = 0; i < EDID_LENGTH; i++) for (i = 0; i < EDID_LENGTH; i++)
csum += raw_edid[i]; csum += raw_edid[i];
if (csum) { if (csum) {
DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); if (print_bad_edid) {
DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
}
/* allow CEA to slide through, switches mangle this */ /* allow CEA to slide through, switches mangle this */
if (raw_edid[0] != 0x02) if (raw_edid[0] != 0x02)
...@@ -207,7 +209,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block) ...@@ -207,7 +209,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block)
return 1; return 1;
bad: bad:
if (raw_edid) { if (raw_edid && print_bad_edid) {
printk(KERN_ERR "Raw EDID:\n"); printk(KERN_ERR "Raw EDID:\n");
print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1, print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
raw_edid, EDID_LENGTH, false); raw_edid, EDID_LENGTH, false);
...@@ -231,7 +233,7 @@ bool drm_edid_is_valid(struct edid *edid) ...@@ -231,7 +233,7 @@ bool drm_edid_is_valid(struct edid *edid)
return false; return false;
for (i = 0; i <= edid->extensions; i++) for (i = 0; i <= edid->extensions; i++)
if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i)) if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true))
return false; return false;
return true; return true;
...@@ -316,6 +318,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) ...@@ -316,6 +318,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
{ {
int i, j = 0, valid_extensions = 0; int i, j = 0, valid_extensions = 0;
u8 *block, *new; u8 *block, *new;
bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
return NULL; return NULL;
...@@ -324,7 +327,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) ...@@ -324,7 +327,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
goto out; goto out;
if (drm_edid_block_valid(block, 0)) if (drm_edid_block_valid(block, 0, print_bad_edid))
break; break;
if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
connector->null_edid_counter++; connector->null_edid_counter++;
...@@ -349,7 +352,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) ...@@ -349,7 +352,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
block + (valid_extensions + 1) * EDID_LENGTH, block + (valid_extensions + 1) * EDID_LENGTH,
j, EDID_LENGTH)) j, EDID_LENGTH))
goto out; goto out;
if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j)) { if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) {
valid_extensions++; valid_extensions++;
break; break;
} }
...@@ -372,8 +375,11 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) ...@@ -372,8 +375,11 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
return block; return block;
carp: carp:
dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", if (print_bad_edid) {
drm_get_connector_name(connector), j); dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
drm_get_connector_name(connector), j);
}
connector->bad_edid_counter++;
out: out:
kfree(block); kfree(block);
......
...@@ -123,6 +123,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name, ...@@ -123,6 +123,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
int fwsize, expected; int fwsize, expected;
int builtin = 0, err = 0; int builtin = 0, err = 0;
int i, valid_extensions = 0; int i, valid_extensions = 0;
bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
pdev = platform_device_register_simple(connector_name, -1, NULL, 0); pdev = platform_device_register_simple(connector_name, -1, NULL, 0);
if (IS_ERR(pdev)) { if (IS_ERR(pdev)) {
...@@ -173,7 +174,8 @@ static u8 *edid_load(struct drm_connector *connector, char *name, ...@@ -173,7 +174,8 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
} }
memcpy(edid, fwdata, fwsize); memcpy(edid, fwdata, fwsize);
if (!drm_edid_block_valid(edid, 0)) { if (!drm_edid_block_valid(edid, 0, print_bad_edid)) {
connector->bad_edid_counter++;
DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ", DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
name); name);
kfree(edid); kfree(edid);
...@@ -185,7 +187,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name, ...@@ -185,7 +187,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
if (i != valid_extensions + 1) if (i != valid_extensions + 1)
memcpy(edid + (valid_extensions + 1) * EDID_LENGTH, memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
edid + i * EDID_LENGTH, EDID_LENGTH); edid + i * EDID_LENGTH, EDID_LENGTH);
if (drm_edid_block_valid(edid + i * EDID_LENGTH, i)) if (drm_edid_block_valid(edid + i * EDID_LENGTH, i, print_bad_edid))
valid_extensions++; valid_extensions++;
} }
......
...@@ -590,6 +590,7 @@ struct drm_connector { ...@@ -590,6 +590,7 @@ struct drm_connector {
int video_latency[2]; /* [0]: progressive, [1]: interlaced */ int video_latency[2]; /* [0]: progressive, [1]: interlaced */
int audio_latency[2]; int audio_latency[2];
int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
unsigned bad_edid_counter;
}; };
/** /**
...@@ -1032,7 +1033,7 @@ extern int drm_add_modes_noedid(struct drm_connector *connector, ...@@ -1032,7 +1033,7 @@ extern int drm_add_modes_noedid(struct drm_connector *connector,
int hdisplay, int vdisplay); int hdisplay, int vdisplay);
extern int drm_edid_header_is_valid(const u8 *raw_edid); extern int drm_edid_header_is_valid(const u8 *raw_edid);
extern bool drm_edid_block_valid(u8 *raw_edid, int block); extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid);
extern bool drm_edid_is_valid(struct edid *edid); extern bool drm_edid_is_valid(struct edid *edid);
struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
int hsize, int vsize, int fresh, int hsize, int vsize, int fresh,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment