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: Jerome Glisse <jglisse@redhat.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
09e7dcf081
commit
0b2443ed4e
3 changed files with 20 additions and 11 deletions
|
@ -158,7 +158,7 @@ MODULE_PARM_DESC(edid_fixup,
|
|||
* Sanity check the EDID block (base or extension). Return 0 if the block
|
||||
* 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;
|
||||
u8 csum = 0;
|
||||
|
@ -181,7 +181,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block)
|
|||
for (i = 0; i < EDID_LENGTH; i++)
|
||||
csum += raw_edid[i];
|
||||
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 */
|
||||
if (raw_edid[0] != 0x02)
|
||||
|
@ -207,7 +209,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block)
|
|||
return 1;
|
||||
|
||||
bad:
|
||||
if (raw_edid) {
|
||||
if (raw_edid && print_bad_edid) {
|
||||
printk(KERN_ERR "Raw EDID:\n");
|
||||
print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
|
||||
raw_edid, EDID_LENGTH, false);
|
||||
|
@ -231,7 +233,7 @@ bool drm_edid_is_valid(struct edid *edid)
|
|||
return false;
|
||||
|
||||
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 true;
|
||||
|
@ -316,6 +318,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|||
{
|
||||
int i, j = 0, valid_extensions = 0;
|
||||
u8 *block, *new;
|
||||
bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
|
||||
|
||||
if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
|
||||
return NULL;
|
||||
|
@ -324,7 +327,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|||
for (i = 0; i < 4; i++) {
|
||||
if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
|
||||
goto out;
|
||||
if (drm_edid_block_valid(block, 0))
|
||||
if (drm_edid_block_valid(block, 0, print_bad_edid))
|
||||
break;
|
||||
if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
|
||||
connector->null_edid_counter++;
|
||||
|
@ -349,7 +352,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|||
block + (valid_extensions + 1) * EDID_LENGTH,
|
||||
j, EDID_LENGTH))
|
||||
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++;
|
||||
break;
|
||||
}
|
||||
|
@ -372,8 +375,11 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
|||
return block;
|
||||
|
||||
carp:
|
||||
dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
|
||||
drm_get_connector_name(connector), j);
|
||||
if (print_bad_edid) {
|
||||
dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
|
||||
drm_get_connector_name(connector), j);
|
||||
}
|
||||
connector->bad_edid_counter++;
|
||||
|
||||
out:
|
||||
kfree(block);
|
||||
|
|
|
@ -123,6 +123,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
|
|||
int fwsize, expected;
|
||||
int builtin = 0, err = 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);
|
||||
if (IS_ERR(pdev)) {
|
||||
|
@ -173,7 +174,8 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
|
|||
}
|
||||
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 ",
|
||||
name);
|
||||
kfree(edid);
|
||||
|
@ -185,7 +187,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
|
|||
if (i != valid_extensions + 1)
|
||||
memcpy(edid + (valid_extensions + 1) * 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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -590,6 +590,7 @@ struct drm_connector {
|
|||
int video_latency[2]; /* [0]: progressive, [1]: interlaced */
|
||||
int audio_latency[2];
|
||||
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,
|
|||
int hdisplay, int vdisplay);
|
||||
|
||||
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);
|
||||
struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
|
||||
int hsize, int vsize, int fresh,
|
||||
|
|
Loading…
Reference in a new issue