Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -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) {
		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:
	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);
+4 −2
Original line number Diff line number Diff line
@@ -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++;
	}

+2 −1
Original line number Diff line number Diff line
@@ -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,