Skip to contentSkip to conversation

FAILED: patch "[PATCH] drm/displayid: add quirk to ignore DisplayID checksum errors" failed to apply to 6.18-stable tree

PATCH New [email protected] 2 participants 4 messages Dec 29, 2025 – Dec 31, 2025

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 83cbb4d33dc22b0ca1a4e85c6e892c9b729e28d4
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025122944-trimester-congrats-2c82@gregkh' --subject-prefix 'PATCH 6.18.y' HEAD^..

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 83cbb4d33dc22b0ca1a4e85c6e892c9b729e28d4 Mon Sep 17 00:00:00 2001
From: Jani Nikula <[email protected]>
Date: Tue, 28 Oct 2025 22:07:27 +0200
Subject: [PATCH] drm/displayid: add quirk to ignore DisplayID checksum errors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add a mechanism for DisplayID specific quirks, and add the first quirk to ignore DisplayID section checksum errors.

It would be quite inconvenient to pass existing EDID quirks from drm_edid.c for DisplayID parsing. Not all places doing DisplayID iteration have the quirks readily available, and would have to pass it in all places. Simply add a separate array of DisplayID specific EDID quirks. We do end up checking it every time we iterate DisplayID blocks, but hopefully the number of quirks remains small.

There are a few laptop models with DisplayID checksum failures, leading to higher refresh rates only present in the DisplayID blocks being ignored. Add a quirk for the panel in the machines.

drivers/gpu/drm/drm_displayid.c +37 -4
index 20b453d2b854..58d0bb6d2676 100644
@@ -9,6 +9,34 @@
 #include "drm_crtc_internal.h"
 #include "drm_displayid_internal.h"
 
+enum {
+	QUIRK_IGNORE_CHECKSUM,
+};
+
+struct displayid_quirk {
+	const struct drm_edid_ident ident;
+	u8 quirks;
+};
+
+static const struct displayid_quirk quirks[] = {
+	{
+		.ident = DRM_EDID_IDENT_INIT('C', 'S', 'O', 5142, "MNE007ZA1-5"),
+		.quirks = BIT(QUIRK_IGNORE_CHECKSUM),
+	},
+};
+
+static u8 get_quirks(const struct drm_edid *drm_edid)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(quirks); i++) {
+		if (drm_edid_match(drm_edid, &quirks[i].ident))
+			return quirks[i].quirks;
+	}
+
+	return 0;
+}
+
 static const struct displayid_header *
 displayid_get_header(const u8 *displayid, int length, int index)
 {
@@ -23,7 +51,7 @@ displayid_get_header(const u8 *displayid, int length, int index)
 }
 
 static const struct displayid_header *
-validate_displayid(const u8 *displayid, int length, int idx)
+validate_displayid(const u8 *displayid, int length, int idx, bool ignore_checksum)
 {
 	int i, dispid_length;
 	u8 csum = 0;
@@ -41,8 +69,11 @@ validate_displayid(const u8 *displayid, int length, int idx)
 	for (i = 0; i < dispid_length; i++)
 		csum += displayid[idx + i];
 	if (csum) {
-		DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);
-		return ERR_PTR(-EINVAL);
+		DRM_NOTE("DisplayID checksum invalid, remainder is %d%s\n", csum,
+			 ignore_checksum ? " (ignoring)" : "");
+
+		if (!ignore_checksum)
+			return ERR_PTR(-EINVAL);
 	}
 
 	return base;
@@ -52,6 +83,7 @@ static const u8 *find_next_displayid_extension(struct displayid_iter *iter)
 {
 	const struct displayid_header *base;
 	const u8 *displayid;
+	bool ignore_checksum = iter->quirks & BIT(QUIRK_IGNORE_CHECKSUM);
 
 	displayid = drm_edid_find_extension(iter->drm_edid, DISPLAYID_EXT, &iter->ext_index);
 	if (!displayid)
@@ -61,7 +93,7 @@ static const u8 *find_next_displayid_extension(struct displayid_iter *iter)
 	iter->length = EDID_LENGTH - 1;
 	iter->idx = 1;
 
-	base = validate_displayid(displayid, iter->length, iter->idx);
+	base = validate_displayid(displayid, iter->length, iter->idx, ignore_checksum);
 	if (IS_ERR(base))
 		return NULL;
 
@@ -76,6 +108,7 @@ void displayid_iter_edid_begin(const struct drm_edid *drm_edid,
 	memset(iter, 0, sizeof(*iter));
 
 	iter->drm_edid = drm_edid;
+	iter->quirks = get_quirks(drm_edid);
 }
 
 static const struct displayid_block *
drivers/gpu/drm/drm_displayid_internal.h +2 -0
index 957dd0619f5c..5b1b32f73516 100644
@@ -167,6 +167,8 @@ struct displayid_iter {
 
 	u8 version;
 	u8 primary_use;
+
+	u8 quirks;
 };
 
 void displayid_iter_edid_begin(const struct drm_edid *drm_edid,
maintainer
#1 lore raw

PATCH 1/3 drm/displayid: pass iter to drm_find_displayid_extension()

From: Jani Nikula <[email protected]>

[ Upstream commit 520f37c30992fd0c212a34fbe99c062b7a3dc52e ]

It's more convenient to pass iter than a handful of its members to drm_find_displayid_extension(), especially as we're about to add another member.

Rename the function find_next_displayid_extension() while at it, to be more descriptive.

Stable-dep-of: 83cbb4d33dc2 ("drm/displayid: add quirk to ignore DisplayID checksum errors")

---
 drivers/gpu/drm/drm_displayid.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)
drivers/gpu/drm/drm_displayid.c +7 -12
index b4fd43783c50..20b453d2b854 100644
@@ -48,26 +48,24 @@ validate_displayid(const u8 *displayid, int length, int idx)
 	return base;
 }
 
-static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid,
-					      int *length, int *idx,
-					      int *ext_index)
+static const u8 *find_next_displayid_extension(struct displayid_iter *iter)
 {
 	const struct displayid_header *base;
 	const u8 *displayid;
 
-	displayid = drm_edid_find_extension(drm_edid, DISPLAYID_EXT, ext_index);
+	displayid = drm_edid_find_extension(iter->drm_edid, DISPLAYID_EXT, &iter->ext_index);
 	if (!displayid)
 		return NULL;
 
 	/* EDID extensions block checksum isn't for us */
-	*length = EDID_LENGTH - 1;
-	*idx = 1;
+	iter->length = EDID_LENGTH - 1;
+	iter->idx = 1;
 
-	base = validate_displayid(displayid, *length, *idx);
+	base = validate_displayid(displayid, iter->length, iter->idx);
 	if (IS_ERR(base))
 		return NULL;
 
-	*length = *idx + sizeof(*base) + base->bytes;
+	iter->length = iter->idx + sizeof(*base) + base->bytes;
 
 	return displayid;
 }
@@ -126,10 +124,7 @@ __displayid_iter_next(struct displayid_iter *iter)
 		/* The first section we encounter is the base section */
 		bool base_section = !iter->section;
 
-		iter->section = drm_find_displayid_extension(iter->drm_edid,
-							     &iter->length,
-							     &iter->idx,
-							     &iter->ext_index);
+		iter->section = find_next_displayid_extension(iter);
 		if (!iter->section) {
 			iter->drm_edid = NULL;
 			return NULL;
Signature · 1 line
2.51.0
maintainer
#2 lore raw

PATCH 2/3 drm/edid: add DRM_EDID_IDENT_INIT() to initialize struct drm_edid_ident

From: Jani Nikula <[email protected]>

[ Upstream commit 8b61583f993589a64c061aa91b44f5bd350d90a5 ]

Add a convenience helper for initializing struct drm_edid_ident.

Stable-dep-of: 83cbb4d33dc2 ("drm/displayid: add quirk to ignore DisplayID checksum errors")

---
 include/drm/drm_edid.h | 6 ++++++
 1 file changed, 6 insertions(+)
include/drm/drm_edid.h +6 -0
index 3d1aecfec9b2..04f7a7f1f108 100644
@@ -340,6 +340,12 @@ struct drm_edid_ident {
 	const char *name;
 };
 
+#define DRM_EDID_IDENT_INIT(_vend_chr_0, _vend_chr_1, _vend_chr_2, _product_id, _name) \
+{ \
+	.panel_id = drm_edid_encode_panel_id(_vend_chr_0, _vend_chr_1, _vend_chr_2, _product_id), \
+	.name = _name, \
+}
+
 #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
 
 /* Short Audio Descriptor */
Signature · 1 line
2.51.0
maintainer
#3 lore raw

PATCH 3/3 drm/displayid: add quirk to ignore DisplayID checksum errors

In reply to Sasha Levin

From: Jani Nikula <[email protected]>

[ Upstream commit 83cbb4d33dc22b0ca1a4e85c6e892c9b729e28d4 ]

Add a mechanism for DisplayID specific quirks, and add the first quirk to ignore DisplayID section checksum errors.

It would be quite inconvenient to pass existing EDID quirks from drm_edid.c for DisplayID parsing. Not all places doing DisplayID iteration have the quirks readily available, and would have to pass it in all places. Simply add a separate array of DisplayID specific EDID quirks. We do end up checking it every time we iterate DisplayID blocks, but hopefully the number of quirks remains small.

There are a few laptop models with DisplayID checksum failures, leading to higher refresh rates only present in the DisplayID blocks being ignored. Add a quirk for the panel in the machines.

---
 drivers/gpu/drm/drm_displayid.c          | 41 +++++++++++++++++++++---
 drivers/gpu/drm/drm_displayid_internal.h |  2 ++
 2 files changed, 39 insertions(+), 4 deletions(-)
drivers/gpu/drm/drm_displayid.c +37 -4
index 20b453d2b854..58d0bb6d2676 100644
@@ -9,6 +9,34 @@
 #include "drm_crtc_internal.h"
 #include "drm_displayid_internal.h"
 
+enum {
+	QUIRK_IGNORE_CHECKSUM,
+};
+
+struct displayid_quirk {
+	const struct drm_edid_ident ident;
+	u8 quirks;
+};
+
+static const struct displayid_quirk quirks[] = {
+	{
+		.ident = DRM_EDID_IDENT_INIT('C', 'S', 'O', 5142, "MNE007ZA1-5"),
+		.quirks = BIT(QUIRK_IGNORE_CHECKSUM),
+	},
+};
+
+static u8 get_quirks(const struct drm_edid *drm_edid)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(quirks); i++) {
+		if (drm_edid_match(drm_edid, &quirks[i].ident))
+			return quirks[i].quirks;
+	}
+
+	return 0;
+}
+
 static const struct displayid_header *
 displayid_get_header(const u8 *displayid, int length, int index)
 {
@@ -23,7 +51,7 @@ displayid_get_header(const u8 *displayid, int length, int index)
 }
 
 static const struct displayid_header *
-validate_displayid(const u8 *displayid, int length, int idx)
+validate_displayid(const u8 *displayid, int length, int idx, bool ignore_checksum)
 {
 	int i, dispid_length;
 	u8 csum = 0;
@@ -41,8 +69,11 @@ validate_displayid(const u8 *displayid, int length, int idx)
 	for (i = 0; i < dispid_length; i++)
 		csum += displayid[idx + i];
 	if (csum) {
-		DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);
-		return ERR_PTR(-EINVAL);
+		DRM_NOTE("DisplayID checksum invalid, remainder is %d%s\n", csum,
+			 ignore_checksum ? " (ignoring)" : "");
+
+		if (!ignore_checksum)
+			return ERR_PTR(-EINVAL);
 	}
 
 	return base;
@@ -52,6 +83,7 @@ static const u8 *find_next_displayid_extension(struct displayid_iter *iter)
 {
 	const struct displayid_header *base;
 	const u8 *displayid;
+	bool ignore_checksum = iter->quirks & BIT(QUIRK_IGNORE_CHECKSUM);
 
 	displayid = drm_edid_find_extension(iter->drm_edid, DISPLAYID_EXT, &iter->ext_index);
 	if (!displayid)
@@ -61,7 +93,7 @@ static const u8 *find_next_displayid_extension(struct displayid_iter *iter)
 	iter->length = EDID_LENGTH - 1;
 	iter->idx = 1;
 
-	base = validate_displayid(displayid, iter->length, iter->idx);
+	base = validate_displayid(displayid, iter->length, iter->idx, ignore_checksum);
 	if (IS_ERR(base))
 		return NULL;
 
@@ -76,6 +108,7 @@ void displayid_iter_edid_begin(const struct drm_edid *drm_edid,
 	memset(iter, 0, sizeof(*iter));
 
 	iter->drm_edid = drm_edid;
+	iter->quirks = get_quirks(drm_edid);
 }
 
 static const struct displayid_block *
drivers/gpu/drm/drm_displayid_internal.h +2 -0
index 957dd0619f5c..5b1b32f73516 100644
@@ -167,6 +167,8 @@ struct displayid_iter {
 
 	u8 version;
 	u8 primary_use;
+
+	u8 quirks;
 };
 
 void displayid_iter_edid_begin(const struct drm_edid *drm_edid,
Signature · 1 line
2.51.0