From: Jerome Glisse <jgli...@redhat.com>

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 at redhat.com>
---
 drivers/gpu/drm/drm_edid.c      | 22 ++++++++++++++--------
 drivers/gpu/drm/drm_edid_load.c |  6 ++++--
 include/drm/drm_crtc.h          |  3 ++-
 3 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a8743c3..7380ee3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -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;
@@ -303,6 +305,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;
@@ -311,7 +314,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++;
@@ -336,7 +339,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;
                        }
@@ -359,8 +362,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);
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
index 66d4a28..14f46dd 100644
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -123,6 +123,7 @@ static int 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 int 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 int 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++;
        }

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index bac55c2..1a2987b 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -594,6 +594,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;
 };

 /**
@@ -1038,7 +1039,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,
-- 
1.7.11.2

Reply via email to