mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Mark Brown <broonie@kernel.org>
To: Dave Airlie <airlied@redhat.com>, DRI <dri-devel@lists.freedesktop.org>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Linux Next Mailing List <linux-next@vger.kernel.org>,
	Lyude Paul <lyude@redhat.com>,
	Mohamed Ahmed <mohamedahmedegypt2001@gmail.com>,
	Wentao Liang <vulab@iscas.ac.cn>
Subject: linux-next: manual merge of the drm tree with the drm-misc-fixes tree
Date: Fri, 18 Sep 2026 12:14:17 +0100	[thread overview]
Message-ID: <aq0dCW8iD494oG7j@sirena.org.uk> (raw)

[-- Attachment #1: Type: text/plain, Size: 10260 bytes --]

Hi all,

Today's linux-next merge of the drm tree got a conflict in:

  drivers/gpu/drm/nouveau/nouveau_connector.c

between commit:

  1e04611d37355 ("drm/nouveau: Fix runtime PM leak in nouveau_connector_detect()")

from the drm-misc-fixes tree and commit:

  0116f19db5931 ("drm/nouveau: honor HF-EEODB EDIDs by converting to struct drm_edid")

from the drm tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --combined drivers/gpu/drm/nouveau/nouveau_connector.c
index 4cfc9c7c2ae0c,cc3caf8de64b0..0000000000000
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@@ -397,7 -397,8 +397,8 @@@ nouveau_connector_destroy(struct drm_co
  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
  	nvif_event_dtor(&nv_connector->irq);
  	nvif_event_dtor(&nv_connector->hpd);
- 	kfree(nv_connector->edid);
+ 	cancel_work_sync(&nv_connector->irq_work);
+ 	drm_edid_free(nv_connector->drm_edid);
  	drm_connector_unregister(connector);
  	drm_connector_cleanup(connector);
  	if (nv_connector->aux.transfer)
@@@ -469,6 -470,36 +470,36 @@@ nouveau_connector_ddc_detect(struct drm
  	return found;
  }
  
+ static void
+ nouveau_connector_set_edid(struct nouveau_connector *nv_connector,
+ 			   const struct drm_edid *drm_edid)
+ {
+ 	if (nv_connector->drm_edid == drm_edid)
+ 		return;
+ 
+ 	/* Updates the EDID property and display_info with HF-EEODB-aware
+ 	 * sizing. The legacy helpers truncate both to what EDID byte 126
+ 	 * admits, hiding the DisplayID extension blocks that carry the
+ 	 * high-refresh timings.
+ 	 */
+ 	drm_edid_connector_update(&nv_connector->base, drm_edid);
+ 
+ 	drm_edid_free(nv_connector->drm_edid);
+ 	nv_connector->drm_edid = drm_edid;
+ 
+ 	/* The SPWG link-count byte lives in a vendor descriptor drm has no
+ 	 * accessor for. Peek at it once here so nothing else needs the raw
+ 	 * EDID.
+ 	 */
+ 	nv_connector->spwg_links = 0;
+ 	if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) {
+ 		const u8 *raw = (const u8 *)drm_edid_raw(drm_edid);
+ 
+ 		if (raw)
+ 			nv_connector->spwg_links = raw[121] == 2 ? 2 : 1;
+ 	}
+ }
+ 
  static struct nouveau_encoder *
  nouveau_connector_of_detect(struct drm_connector *connector)
  {
@@@ -490,8 -521,17 +521,17 @@@
  		int idx = name ? name[strlen(name) - 1] - 'A' : 0;
  
  		if (nv_encoder->dcb->i2c_index == idx && edid) {
- 			nv_connector->edid =
- 				kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
+ 			const struct drm_edid *drm_edid =
+ 				drm_edid_alloc(edid, EDID_LENGTH);
+ 
+ 			/* Firmware-provided, so validate it like the DDC
+ 			 * readers would.
+ 			 */
+ 			if (drm_edid && !drm_edid_valid(drm_edid)) {
+ 				drm_edid_free(drm_edid);
+ 				drm_edid = NULL;
+ 			}
+ 			nouveau_connector_set_edid(nv_connector, drm_edid);
  			return nv_encoder;
  		}
  	}
@@@ -546,17 -586,23 +586,23 @@@ nouveau_connector_set_encoder(struct dr
  	}
  }
  
- static void
- nouveau_connector_set_edid(struct nouveau_connector *nv_connector,
- 			   struct edid *edid)
- {
- 	if (nv_connector->edid != edid) {
- 		struct edid *old_edid = nv_connector->edid;
+ struct nouveau_rm_edid {
+ 	u8 *data;
+ 	size_t size;
+ };
  
- 		drm_connector_update_edid_property(&nv_connector->base, edid);
- 		kfree(old_edid);
- 		nv_connector->edid = edid;
- 	}
+ static int
+ nouveau_connector_rm_edid_block(void *context, u8 *buf, unsigned int block,
+ 				size_t len)
+ {
+ 	struct nouveau_rm_edid *rm = context;
+ 	size_t offset = (size_t)block * EDID_LENGTH;
+ 
+ 	if (offset + len > rm->size)
+ 		return -EINVAL;
+ 
+ 	memcpy(buf, rm->data + offset, len);
+ 	return 0;
  }
  
  static enum drm_connector_status
@@@ -590,25 -636,37 +636,37 @@@ nouveau_connector_detect(struct drm_con
  
  	nv_encoder = nouveau_connector_ddc_detect(connector);
  	if (nv_encoder) {
- 		struct edid *new_edid = NULL;
+ 		const struct drm_edid *new_edid = NULL;
  
  		if (nv_encoder->i2c) {
  			if ((vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
  			    nv_connector->type == DCB_CONNECTOR_LVDS)
- 				new_edid = drm_get_edid_switcheroo(connector, nv_encoder->i2c);
+ 				new_edid = drm_edid_read_switcheroo(connector, nv_encoder->i2c);
  			else
- 				new_edid = drm_get_edid(connector, nv_encoder->i2c);
+ 				new_edid = drm_edid_read_ddc(connector, nv_encoder->i2c);
  		} else {
- 			ret = nvif_outp_edid_get(&nv_encoder->outp, (u8 **)&new_edid);
- 			if (ret < 0) {
- 				pm_runtime_mark_last_busy(dev->dev);
- 				pm_runtime_put_autosuspend(dev->dev);
- 				return connector_status_disconnected;
+ 			struct nouveau_rm_edid rm = {};
+ 
+ 			/* RM (which owns the DDC pads on GSP boards) reads the
+ 			 * EDID whole and returns its true size, which for an
+ 			 * HF-EEODB EDID exceeds what byte 126 admits. Serve it
+ 			 * through drm's block reader so EEODB sizing, block
+ 			 * validation, and the debugfs EDID override all apply.
+ 			 * A failed read is treated like an empty DDC read,
+ 			 * which releases the runtime-PM reference.
+ 			 */
+ 			ret = nvif_outp_edid_get(&nv_encoder->outp, &rm.data);
+ 			if (ret >= 0) {
+ 				rm.size = ret;
+ 				new_edid = drm_edid_read_custom(connector,
+ 								nouveau_connector_rm_edid_block,
+ 								&rm);
+ 				kfree(rm.data);
  			}
  		}
  
  		nouveau_connector_set_edid(nv_connector, new_edid);
- 		if (!nv_connector->edid) {
+ 		if (!nv_connector->drm_edid) {
  			NV_ERROR(drm, "DDC responded, but no EDID for %s\n",
  				 connector->name);
  			goto detect_analog;
@@@ -629,7 -687,7 +687,7 @@@
  				    nv_partner->dcb->type == DCB_OUTPUT_TMDS) ||
  				   (nv_encoder->dcb->type == DCB_OUTPUT_TMDS &&
  				    nv_partner->dcb->type == DCB_OUTPUT_ANALOG))) {
- 			if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
+ 			if (drm_edid_is_digital(nv_connector->drm_edid))
  				type = DCB_OUTPUT_TMDS;
  			else
  				type = DCB_OUTPUT_ANALOG;
@@@ -641,7 -699,8 +699,8 @@@
  		conn_status = connector_status_connected;
  
  		if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
- 			drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid);
+ 			drm_dp_cec_attach(&nv_connector->aux,
+ 					  connector->display_info.source_physical_address);
  
  		goto out;
  	} else {
@@@ -673,7 -732,7 +732,7 @@@ detect_analog
  	}
  
   out:
- 	if (!nv_connector->edid)
+ 	if (!nv_connector->drm_edid)
  		drm_dp_cec_unset_edid(&nv_connector->aux);
  
  	pm_runtime_mark_last_busy(dev->dev);
@@@ -689,7 -748,7 +748,7 @@@ nouveau_connector_detect_lvds(struct dr
  	struct nouveau_drm *drm = nouveau_drm(dev);
  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
  	struct nouveau_encoder *nv_encoder = NULL;
- 	struct edid *edid = NULL;
+ 	const struct drm_edid *edid = NULL;
  	enum drm_connector_status status = connector_status_disconnected;
  
  	nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
@@@ -700,7 -759,7 +759,7 @@@
  	if (!drm->vbios.fp_no_ddc) {
  		status = nouveau_connector_detect(connector, force);
  		if (status == connector_status_connected) {
- 			edid = nv_connector->edid;
+ 			edid = nv_connector->drm_edid;
  			goto out;
  		}
  	}
@@@ -736,11 -795,20 +795,20 @@@
  	 * stored for the panel stored in them.
  	 */
  	if (!drm->vbios.fp_no_ddc) {
- 		edid = (struct edid *)nouveau_bios_embedded_edid(dev);
- 		if (edid) {
- 			edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
+ 		const void *embedded = nouveau_bios_embedded_edid(dev);
+ 
+ 		if (embedded) {
+ 			edid = drm_edid_alloc(embedded, EDID_LENGTH);
+ 			/* The panel is there either way, so report it
+ 			 * connected and let the probe helper fall back to a
+ 			 * default mode if the EDID itself is unusable.
+ 			 */
  			if (edid)
  				status = connector_status_connected;
+ 			if (edid && !drm_edid_valid(edid)) {
+ 				drm_edid_free(edid);
+ 				edid = NULL;
+ 			}
  		}
  	}
  
@@@ -889,7 -957,7 +957,7 @@@ nouveau_connector_detect_depth(struct d
  	bool duallink;
  
  	/* if the edid is feeling nice enough to provide this info, use it */
- 	if (nv_connector->edid && connector->display_info.bpc)
+ 	if (nv_connector->drm_edid && connector->display_info.bpc)
  		return;
  
  	/* EDID 1.4 is *supposed* to be supported on eDP, but, Apple... */
@@@ -916,9 -984,8 +984,8 @@@
  	/* LVDS: DDC panel, need to first determine the number of links to
  	 * know which if_is_24bit flag to check...
  	 */
- 	if (nv_connector->edid &&
- 	    nv_connector->type == DCB_CONNECTOR_LVDS_SPWG)
- 		duallink = ((u8 *)nv_connector->edid)[121] == 2;
+ 	if (nv_connector->spwg_links)
+ 		duallink = nv_connector->spwg_links == 2;
  	else
  		duallink = mode->clock >= bios->fp.duallink_transition_clk;
  
@@@ -976,12 -1043,17 +1043,17 @@@ nouveau_connector_get_modes(struct drm_
  		nv_connector->native_mode = NULL;
  	}
  
- 	if (nv_connector->edid)
- 		ret = drm_add_edid_modes(connector, nv_connector->edid);
- 	else
- 	if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS &&
- 	    (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
- 	     drm->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
+ 	if (nv_connector->drm_edid) {
+ 		/* The probe helper clears the property and display_info for
+ 		 * a forced-off connector without calling detect(). Re-sync
+ 		 * from our copy then, since add_modes() reads the property.
+ 		 */
+ 		if (!connector->edid_blob_ptr)
+ 			drm_edid_connector_update(connector, nv_connector->drm_edid);
+ 		ret = drm_edid_connector_add_modes(connector);
+ 	} else if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS &&
+ 		   (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
+ 		    drm->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
  		struct drm_display_mode mode;
  
  		nouveau_bios_fp_mode(dev, &mode);

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

             reply	other threads:[~2026-09-18 11:14 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18 11:14 Mark Brown [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-09-18 11:14 Mark Brown
2026-08-12 15:45 Mark Brown
2026-08-12 12:20 Mark Brown
2026-06-11 13:54 Mark Brown
2026-06-16  9:16 ` Geert Uytterhoeven
2026-03-20 14:17 Mark Brown
2026-03-20 15:39 ` Boris Brezillon
2026-04-08 17:26   ` Mark Brown
2026-04-09  7:47     ` Boris Brezillon
2026-03-18 14:36 Mark Brown
2026-03-18 15:49 ` Luca Ceresoli
2026-03-18 18:20   ` Cristian Ciocaltea
2026-01-05  2:21 Stephen Rothwell
2025-08-20  1:21 Stephen Rothwell
2025-08-20 10:30 ` Danilo Krummrich
2025-08-20 21:29   ` Stephen Rothwell
2025-07-18  4:41 Stephen Rothwell
2025-07-18  6:27 ` Thomas Zimmermann
2025-01-14  1:30 Stephen Rothwell
2023-11-22  0:29 Stephen Rothwell
2023-11-28 10:04 ` Geert Uytterhoeven
2023-09-28  2:05 Stephen Rothwell
2023-06-27  1:54 Stephen Rothwell
2023-07-11  1:17 ` Stephen Rothwell
2022-11-21  2:06 Stephen Rothwell
2022-07-11  2:47 Stephen Rothwell
2022-07-11  8:05 ` Christian König
2022-07-17 23:44   ` Stephen Rothwell
2022-07-19  7:35     ` Geert Uytterhoeven
2022-07-27  2:55     ` Stephen Rothwell
2022-07-27  3:24       ` Dave Airlie
2022-07-27  5:37         ` Stephen Rothwell
2022-03-18  0:55 Stephen Rothwell
2022-03-18  1:06 ` Stephen Rothwell
2021-12-22  3:50 Stephen Rothwell
2021-12-22  7:31 ` Christian König
2021-11-29 23:33 Stephen Rothwell
2021-11-30  8:58 ` Maxime Ripard
2021-11-30 20:35   ` Stephen Rothwell
2021-10-22  0:53 Stephen Rothwell
2021-06-17  1:42 Stephen Rothwell
2021-04-09  3:12 Stephen Rothwell
2021-03-18  1:02 Stephen Rothwell
2021-03-18  6:51 ` Tomi Valkeinen
2020-07-28  3:41 Stephen Rothwell
2020-05-01  3:45 Stephen Rothwell
2020-03-01 23:43 Stephen Rothwell
2019-09-15 21:18 Mark Brown
2019-09-16  5:29 ` Vasily Khoruzhick
2019-09-17  2:43   ` Qiang Yu
2019-08-26  3:06 Stephen Rothwell
2019-08-29 10:11 ` james qian wang (Arm Technology China)
2018-11-26  2:37 Stephen Rothwell
2018-03-08  0:47 Stephen Rothwell
2017-12-13 23:59 Stephen Rothwell
2017-01-17  0:59 Stephen Rothwell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aq0dCW8iD494oG7j@sirena.org.uk \
    --to=broonie@kernel.org \
    --cc=airlied@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-next@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=mohamedahmedegypt2001@gmail.com \
    --cc=vulab@iscas.ac.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®