[PATCH 11/17] DRM/KMS/EDID: Avoid failing on krealloc on EDID blocks.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There is no point to call krealloc() to shrink the amount of
memory for EDID blocks: the implementation of krealloc() will
ignore the size change and return the same chunk of memory
anyway.
So far we failed reading EDIDs when krealloc() failed.
This may happen if the size required to store an EDID is larger
than one page and the kernel is not able to find consecutive
pages to allocate.
In this case it is still better to return what we already have
(in most cases the base block) and correct the extension block
flag and the checksum accordingly than to fail completely.

Signed-off-by: Egbert Eich <eich@xxxxxxx>
---
 drivers/gpu/drm/drm_edid.c |   34 +++++++++++++---------------------
 1 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 410a54d..16c06d6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -387,7 +387,7 @@ fixup_blockmaps(u8 **blockp, int eblock_cnt)
 					u8 *tmp_p;
 					tmp_p = krealloc(block, (eblock_cnt + 2) * EDID_LENGTH, GFP_KERNEL);
 					if (!tmp_p)
-						return -ENOMEM;
+						return eblock_cnt;
 					*blockp = block = tmp_p;
 					total_cnt = eblock_cnt + 1;
 				}
@@ -408,27 +408,16 @@ fixup_blockmaps(u8 **blockp, int eblock_cnt)
 	return eblock_cnt;
 }
 
-static int
+static void
 fixup_edid(u8 **blockp, int valid_extensions)
 {
-	u8 *new = NULL;
-
-	if (valid_extensions != (*blockp)[EDID_EXTENSION_FLAG_OFFSET]) {
-
+  if (valid_extensions != (*blockp)[EDID_EXTENSION_FLAG_OFFSET]) {
 		if (valid_extensions)
 			valid_extensions = fixup_blockmaps(blockp, valid_extensions);
 
-		if (valid_extensions >= 0) {
-			(*blockp)[EDID_CHECKSUM_OFFSET] += (*blockp)[EDID_EXTENSION_FLAG_OFFSET] - valid_extensions;
-			(*blockp)[EDID_EXTENSION_FLAG_OFFSET] = valid_extensions;
-			new = krealloc(*blockp, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
-		}
-		if (!new)
-			kfree(*blockp);
-
-		*blockp = new;
+		(*blockp)[EDID_CHECKSUM_OFFSET] += (*blockp)[EDID_EXTENSION_FLAG_OFFSET] - valid_extensions;
+		(*blockp)[EDID_EXTENSION_FLAG_OFFSET] = valid_extensions;
 	}
-	return (new ? valid_extensions : -ENOMEM);
 }
 
 static bool 
@@ -506,8 +495,12 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 		return block;
 
 	new = krealloc(block, (block[EDID_EXTENSION_FLAG_OFFSET] + 1) * EDID_LENGTH, GFP_KERNEL);
-	if (!new)
-		goto out;
+	if (!new) {
+		dev_warn(connector->dev->dev, "%s: cannot allocate memory for %d EDID blocks: trunkating.\n",
+			 drm_get_connector_name(connector), block[EDID_EXTENSION_FLAG_OFFSET] + 1);
+		valid_extensions = 0;
+		goto no_more;
+	}
 	block = new;
 
 	for (j = 1; j <= block[EDID_EXTENSION_FLAG_OFFSET]; j++) {
@@ -594,9 +587,8 @@ drm_validate_edid_blob(struct drm_connector *connector, u8 **blockp, int len)
 						 valid_extensions + 1, print_bad_edid))
 				valid_extensions++;
 		}
-		ret = fixup_edid(blockp, valid_extensions);
-	}
-	if (ret < 0)
+		fixup_edid(blockp, valid_extensions);
+	} else
 		connector->bad_edid_counter++;
 	return ret;
 }
-- 
1.7.7

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel


[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux