From patchwork Tue Mar 4 15:29:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Imre Deak X-Patchwork-Id: 14000957 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BC301C282D6 for ; Tue, 4 Mar 2025 15:29:24 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1672210E5E5; Tue, 4 Mar 2025 15:29:24 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="FLt3TJ5l"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2BCFE10E5C9; Tue, 4 Mar 2025 15:29:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741102163; x=1772638163; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gDVP8RSVfgxI6wfVd/WVYwnRVVI8kagTl5knEBOK8LI=; b=FLt3TJ5ltXUUeh8K0QuFg/LTnuYieEPY5NX6E+YsnaeULmuTf1/Z/Emt tIkdeeKED3+TW0ZDZUPHRjtdiRoXImMMvbVGzzh+21yTqbeI0HBBcNRc1 2uGWZsiSIh8icEpLRMvaTcee9OaE1xjsVM985wpNaQUJqZGqYgzn507D0 3+hwDECPPK4d61W/ZI4JJm4GCbUlOAiSBkuX6QlBnZ6s3tCiW4rEz1YNO aGenXAQagT8IDFz10CDOSV2FbjMWLbVXSPZgJWqYcWgJ0hFFiTxcKe5Nr RBkxW0c8fZVr7wUXi7YXaC/oiLeE96m6C5vwrKNdaUqXw5F985xH12jrh A==; X-CSE-ConnectionGUID: gdjLf+XlQxKLTv35lYh+bg== X-CSE-MsgGUID: /4gbzfevTKagSbaEWXfTIA== X-IronPort-AV: E=McAfee;i="6700,10204,11363"; a="59575806" X-IronPort-AV: E=Sophos;i="6.14,220,1736841600"; d="scan'208";a="59575806" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:23 -0800 X-CSE-ConnectionGUID: qX6rboR9Qx2C+zsR0oP+Nw== X-CSE-MsgGUID: i/ne63GpS2CyXMA8SYiQNw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118921326" Received: from ideak-desk.fi.intel.com ([10.237.72.78]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:21 -0800 From: Imre Deak To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org Cc: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= Subject: [PATCH v5 1/6] drm/i915/hpd: Track HPD pins instead of ports for HPD pulse events Date: Tue, 4 Mar 2025 17:29:12 +0200 Message-ID: <20250304152917.3407080-2-imre.deak@intel.com> X-Mailer: git-send-email 2.44.2 In-Reply-To: <20250304152917.3407080-1-imre.deak@intel.com> References: <20250304152917.3407080-1-imre.deak@intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Track the HPD pin instead of the corresponding encoder ports for pending short/long HPD pulse events. This is how the pending hotplug events are tracked and there is no reason for tracking the pulse events differently. After this change intel_hpd_trigger_irq() will set the short pulse event pending for all encoders using the given HPD pin. This doesn't change the behavior, as atm in case of multiple (2) encoders sharing the same pin only one will have a pulse handler, so for other encoders without a pulse handler the event is ignored. Also setting the pulse event pending for all encoders using the HPD pin is what happens after an actual HPD IRQ, the effect of calling intel_hpd_trigger_irq() should match this. In a following change this also makes it simpler to block the handling of a short/long pulse event on an HPD pin for all the encoders using this HPD pin. Suggested-by: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_core.h | 4 +-- drivers/gpu/drm/i915/display/intel_hotplug.c | 30 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 554870d2494b3..d9952007635e0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -169,8 +169,8 @@ struct intel_hotplug { u32 retry_bits; struct delayed_work reenable_work; - u32 long_port_mask; - u32 short_port_mask; + u32 long_hpd_pin_mask; + u32 short_hpd_pin_mask; struct work_struct dig_port_work; struct work_struct poll_init_work; diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 00d7b1ccf1900..9692b5c01aea9 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -353,28 +353,28 @@ static void i915_digport_work_func(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, display.hotplug.dig_port_work); - u32 long_port_mask, short_port_mask; + u32 long_hpd_pin_mask, short_hpd_pin_mask; struct intel_encoder *encoder; u32 old_bits = 0; spin_lock_irq(&dev_priv->irq_lock); - long_port_mask = dev_priv->display.hotplug.long_port_mask; - dev_priv->display.hotplug.long_port_mask = 0; - short_port_mask = dev_priv->display.hotplug.short_port_mask; - dev_priv->display.hotplug.short_port_mask = 0; + long_hpd_pin_mask = dev_priv->display.hotplug.long_hpd_pin_mask; + dev_priv->display.hotplug.long_hpd_pin_mask = 0; + short_hpd_pin_mask = dev_priv->display.hotplug.short_hpd_pin_mask; + dev_priv->display.hotplug.short_hpd_pin_mask = 0; spin_unlock_irq(&dev_priv->irq_lock); for_each_intel_encoder(&dev_priv->drm, encoder) { struct intel_digital_port *dig_port; - enum port port = encoder->port; + enum hpd_pin pin = encoder->hpd_pin; bool long_hpd, short_hpd; enum irqreturn ret; if (!intel_encoder_has_hpd_pulse(encoder)) continue; - long_hpd = long_port_mask & BIT(port); - short_hpd = short_port_mask & BIT(port); + long_hpd = long_hpd_pin_mask & BIT(pin); + short_hpd = short_hpd_pin_mask & BIT(pin); if (!long_hpd && !short_hpd) continue; @@ -384,7 +384,7 @@ static void i915_digport_work_func(struct work_struct *work) ret = dig_port->hpd_pulse(dig_port, long_hpd); if (ret == IRQ_NONE) { /* fall back to old school hpd */ - old_bits |= BIT(encoder->hpd_pin); + old_bits |= BIT(pin); } } @@ -407,9 +407,10 @@ static void i915_digport_work_func(struct work_struct *work) void intel_hpd_trigger_irq(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_encoder *encoder = &dig_port->base; spin_lock_irq(&i915->irq_lock); - i915->display.hotplug.short_port_mask |= BIT(dig_port->base.port); + i915->display.hotplug.short_hpd_pin_mask |= BIT(encoder->hpd_pin); spin_unlock_irq(&i915->irq_lock); queue_work(i915->display.hotplug.dp_wq, &i915->display.hotplug.dig_port_work); @@ -557,7 +558,6 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, * only the one of them (DP) will have ->hpd_pulse(). */ for_each_intel_encoder(&dev_priv->drm, encoder) { - enum port port = encoder->port; bool long_hpd; pin = encoder->hpd_pin; @@ -577,10 +577,10 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, if (long_hpd) { long_hpd_pulse_mask |= BIT(pin); - dev_priv->display.hotplug.long_port_mask |= BIT(port); + dev_priv->display.hotplug.long_hpd_pin_mask |= BIT(pin); } else { short_hpd_pulse_mask |= BIT(pin); - dev_priv->display.hotplug.short_port_mask |= BIT(port); + dev_priv->display.hotplug.short_hpd_pin_mask |= BIT(pin); } } @@ -920,8 +920,8 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) spin_lock_irq(&dev_priv->irq_lock); - dev_priv->display.hotplug.long_port_mask = 0; - dev_priv->display.hotplug.short_port_mask = 0; + dev_priv->display.hotplug.long_hpd_pin_mask = 0; + dev_priv->display.hotplug.short_hpd_pin_mask = 0; dev_priv->display.hotplug.event_bits = 0; dev_priv->display.hotplug.retry_bits = 0; From patchwork Tue Mar 4 15:29:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Imre Deak X-Patchwork-Id: 14000958 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CA6EEC282D2 for ; Tue, 4 Mar 2025 15:29:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6CB4310E61A; Tue, 4 Mar 2025 15:29:27 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="GTLvPJm6"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6DFD510E5E7; Tue, 4 Mar 2025 15:29:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741102164; x=1772638164; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=C5iee+QwzsSk0/3BpnysiIhC+DG3L7Fa67FR7VBytFw=; b=GTLvPJm6bAfptOreC7GQVwXxAOwDIsJ2UF2dTjGwC31biNFjw6VmwybE gATLb98KHA2Jsz4Tgns6ZyOEtGy3skaU8A8FwWor+GU7PpnQgWD45lWQ9 NeA9EbXESYhFPj2Z1nLl36LpzJh0bTATeUgNf40xRBl7sKm24ibUoBvJm N2/xc/fwFgDQsw/GngI/ACMg0rPxvUrN3KiHa27ke54cW8CkJBbO7b8Xz t5uEdSct4O10yi5YbBjlfmbdpoKl2K7MJy4QSY43VhOKZ3oFBvf2s+vui d+wOIHFDGTP4jZbAqn97kLt46Ke1s+TeoBR6s/OLFT4UetRMev2hcM4YV Q==; X-CSE-ConnectionGUID: kR/ZFjrmTIOm8LJxN5V5Kw== X-CSE-MsgGUID: C7z9MsTAREuV9Jb+NNK8yQ== X-IronPort-AV: E=McAfee;i="6700,10204,11363"; a="59575809" X-IronPort-AV: E=Sophos;i="6.14,220,1736841600"; d="scan'208";a="59575809" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:24 -0800 X-CSE-ConnectionGUID: t9sKeeJfSIqRohdOR6ek7A== X-CSE-MsgGUID: gGge7+VXSYeZfh9ydtHvfg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118921336" Received: from ideak-desk.fi.intel.com ([10.237.72.78]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:23 -0800 From: Imre Deak To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org Subject: [PATCH v5 2/6] drm/i915/hpd: Let an HPD pin be in the disabled state when handling missed IRQs Date: Tue, 4 Mar 2025 17:29:13 +0200 Message-ID: <20250304152917.3407080-3-imre.deak@intel.com> X-Mailer: git-send-email 2.44.2 In-Reply-To: <20250304152917.3407080-1-imre.deak@intel.com> References: <20250304152917.3407080-1-imre.deak@intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" After suspending and resuming the detection on connectors, HPD IRQs that arrived while the detection was suspended, are handled by scheduling the intel_hotplug::hotplug work for them. All HPD pins must be at this point in either the HPD_ENABLED (set for all pins during driver loading/system resuming) or HPD_MARK_DISABLED (set by IRQ storm detection) state: the HPD_DISABLED state for a pin can be set only from the HPD_MARK_DISABLED state by the hotplug work after a storm detection (enabling polling on the given pin/connector), however the hotplug work won't be scheduled while the detection is suspended. A follow-up change will add support for blocking the HPD IRQ handling on a given HPD pin (without disabling the IRQ generation on it), after which it becomes possible to see a pin in the HPD_DISABLED state when unblocking the IRQ handling (since the blocking could've happened for an already disabled pin). Adjust queue_work_for_missed_irqs() accordingly, so that this function can be reused for unblocking the IRQ handling. Signed-off-by: Imre Deak Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hotplug.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 9692b5c01aea9..3fb5feeefa144 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -980,6 +980,7 @@ static void queue_work_for_missed_irqs(struct drm_i915_private *i915) case HPD_MARK_DISABLED: queue_work = true; break; + case HPD_DISABLED: case HPD_ENABLED: break; default: From patchwork Tue Mar 4 15:29:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Imre Deak X-Patchwork-Id: 14000959 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 50984C282DE for ; Tue, 4 Mar 2025 15:29:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E1A9110E61B; Tue, 4 Mar 2025 15:29:27 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="RkPCT8Ur"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6EA6010E617; Tue, 4 Mar 2025 15:29:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741102166; x=1772638166; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OvFq+3sqfm0JgKllKZIpNiitoLY3AhynrExtrjIfHmo=; b=RkPCT8Ur1QIsLQ3WGjkKovYF+Votnhcy49zjl6Wl7AAIpK3KW0v9ChnH Pplt044xREPf6OJXlR8gtqFrGWHCKgSq0opjl9/x1x0DMLTzv8dJaQIJq AWJ3wqkJ9tdIL2aa7xeOWl3GNWFWEmV6L5VgiT04seyyQQtzn4tLhBMpx zX0A1eOI0IQtaVw/qBr72ga9xT9oERzp4lLY8qAwGDKMeW8e4N5975QOu ticfr6ep6ut74wFyZ8wJbh2GlVGj8PAR8h/JVCaT911aqVi9v4dP7+zR5 Etd11pLqpUMcZMbXx3fsNvdZXYrDmjZn7z9aExeUSsX4ObG9aYcnpv1p6 g==; X-CSE-ConnectionGUID: U3J/n8iBSCSwyRFpDsosNA== X-CSE-MsgGUID: WM3SlnEFTf+y3hRJDBWlVg== X-IronPort-AV: E=McAfee;i="6700,10204,11363"; a="59575817" X-IronPort-AV: E=Sophos;i="6.14,220,1736841600"; d="scan'208";a="59575817" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:26 -0800 X-CSE-ConnectionGUID: gsAI92biQqa2N8TDt5Hfrw== X-CSE-MsgGUID: WtDLd5LUSR+zgmDSJ7yn9g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118921358" Received: from ideak-desk.fi.intel.com ([10.237.72.78]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:24 -0800 From: Imre Deak To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org Cc: Jani Nikula , =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= Subject: [PATCH v5 3/6] drm/i915/hpd: Add support for blocking the IRQ handling on an HPD pin Date: Tue, 4 Mar 2025 17:29:14 +0200 Message-ID: <20250304152917.3407080-4-imre.deak@intel.com> X-Mailer: git-send-email 2.44.2 In-Reply-To: <20250304152917.3407080-1-imre.deak@intel.com> References: <20250304152917.3407080-1-imre.deak@intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add support for blocking the IRQ handling on the HPD pin of a given encoder, handling IRQs that arrived while in the blocked state after unblocking the IRQ handling. This will be used by a follow-up change, which blocks/unblocks the IRQ handling around DP link training. This is similar to the intel_hpd_disable/enable() functionality, by also handling encoders/ports with a pulse handler (i.e. also blocking/unblocking the short/long pulse handling) and handling the IRQs arrived in the blocked state after the handling is unblocked (vs. just dropping such IRQs). v2: - Handle encoders without a port assigned to them. - Fix clearing IRQs from intel_hotplug::short_port_mask. v3: - Rename intel_hpd_suspend/resume() to intel_hpd_block/unblock(). (Jani) - Refer to HPD pins as hpd_pin vs. hpd. - Flush dig_port_work in intel_hpd_block() if any encoder using the HPD pin has a pulse handler. v4: - Fix hpd_pin_has_pulse(), checking the encoder's HPD pin. v5: - Rebase on port->hpd_pin tracking. (Ville) Cc: Jani Nikula Cc: Ville Syrjälä Signed-off-by: Imre Deak --- .../gpu/drm/i915/display/intel_display_core.h | 1 + drivers/gpu/drm/i915/display/intel_hotplug.c | 205 +++++++++++++++--- drivers/gpu/drm/i915/display/intel_hotplug.h | 2 + 3 files changed, 183 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index d9952007635e0..fbe890775c2ab 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -159,6 +159,7 @@ struct intel_hotplug { struct { unsigned long last_jiffies; int count; + int blocked_count; enum { HPD_ENABLED = 0, HPD_DISABLED = 1, diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 3fb5feeefa144..cb4e320a1023d 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -349,19 +349,56 @@ static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder) enc_to_dig_port(encoder)->hpd_pulse != NULL; } +static bool hpd_pin_has_pulse(struct intel_display *display, enum hpd_pin pin) +{ + struct intel_encoder *encoder; + + for_each_intel_encoder(display->drm, encoder) { + if (encoder->hpd_pin != pin) + continue; + + if (intel_encoder_has_hpd_pulse(encoder)) + return true; + } + + return false; +} + +static u32 get_blocked_hpd_pins(struct intel_display *display) +{ + struct drm_i915_private *i915 = to_i915(display->drm); + enum hpd_pin pin; + u32 hpd_pins = 0; + + lockdep_assert_held(&i915->irq_lock); + + for_each_hpd_pin(pin) { + if (display->hotplug.stats[pin].blocked_count) + hpd_pins |= BIT(pin); + } + + return hpd_pins; +} + static void i915_digport_work_func(struct work_struct *work) { - struct drm_i915_private *dev_priv = - container_of(work, struct drm_i915_private, display.hotplug.dig_port_work); + struct intel_display *display = + container_of(work, struct intel_display, hotplug.dig_port_work); + struct drm_i915_private *dev_priv = to_i915(display->drm); + struct intel_hotplug *hotplug = &display->hotplug; u32 long_hpd_pin_mask, short_hpd_pin_mask; struct intel_encoder *encoder; + u32 blocked_hpd_pins; u32 old_bits = 0; spin_lock_irq(&dev_priv->irq_lock); - long_hpd_pin_mask = dev_priv->display.hotplug.long_hpd_pin_mask; - dev_priv->display.hotplug.long_hpd_pin_mask = 0; - short_hpd_pin_mask = dev_priv->display.hotplug.short_hpd_pin_mask; - dev_priv->display.hotplug.short_hpd_pin_mask = 0; + + blocked_hpd_pins = get_blocked_hpd_pins(display); + long_hpd_pin_mask = hotplug->long_hpd_pin_mask & ~blocked_hpd_pins; + hotplug->long_hpd_pin_mask &= ~long_hpd_pin_mask; + short_hpd_pin_mask = hotplug->short_hpd_pin_mask & ~blocked_hpd_pins; + hotplug->short_hpd_pin_mask &= ~short_hpd_pin_mask; + spin_unlock_irq(&dev_priv->irq_lock); for_each_intel_encoder(&dev_priv->drm, encoder) { @@ -406,14 +443,18 @@ static void i915_digport_work_func(struct work_struct *work) */ void intel_hpd_trigger_irq(struct intel_digital_port *dig_port) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_display *display = to_intel_display(dig_port); + struct drm_i915_private *i915 = to_i915(display->drm); + struct intel_hotplug *hotplug = &display->hotplug; struct intel_encoder *encoder = &dig_port->base; spin_lock_irq(&i915->irq_lock); - i915->display.hotplug.short_hpd_pin_mask |= BIT(encoder->hpd_pin); - spin_unlock_irq(&i915->irq_lock); - queue_work(i915->display.hotplug.dp_wq, &i915->display.hotplug.dig_port_work); + hotplug->short_hpd_pin_mask |= BIT(encoder->hpd_pin); + if (!(BIT(encoder->hpd_pin) & get_blocked_hpd_pins(display))) + queue_work(hotplug->dp_wq, &hotplug->dig_port_work); + + spin_unlock_irq(&i915->irq_lock); } /* @@ -421,9 +462,10 @@ void intel_hpd_trigger_irq(struct intel_digital_port *dig_port) */ static void i915_hotplug_work_func(struct work_struct *work) { - struct drm_i915_private *dev_priv = - container_of(work, struct drm_i915_private, - display.hotplug.hotplug_work.work); + struct intel_display *display = + container_of(work, struct intel_display, hotplug.hotplug_work.work); + struct drm_i915_private *dev_priv = to_i915(display->drm); + struct intel_hotplug *hotplug = &display->hotplug; struct drm_connector_list_iter conn_iter; struct intel_connector *connector; u32 changed = 0, retry = 0; @@ -431,16 +473,18 @@ static void i915_hotplug_work_func(struct work_struct *work) u32 hpd_retry_bits; struct drm_connector *first_changed_connector = NULL; int changed_connectors = 0; + u32 blocked_hpd_pins; mutex_lock(&dev_priv->drm.mode_config.mutex); drm_dbg_kms(&dev_priv->drm, "running encoder hotplug functions\n"); spin_lock_irq(&dev_priv->irq_lock); - hpd_event_bits = dev_priv->display.hotplug.event_bits; - dev_priv->display.hotplug.event_bits = 0; - hpd_retry_bits = dev_priv->display.hotplug.retry_bits; - dev_priv->display.hotplug.retry_bits = 0; + blocked_hpd_pins = get_blocked_hpd_pins(display); + hpd_event_bits = hotplug->event_bits & ~blocked_hpd_pins; + hotplug->event_bits &= ~hpd_event_bits; + hpd_retry_bits = hotplug->retry_bits & ~blocked_hpd_pins; + hotplug->retry_bits &= ~hpd_retry_bits; /* Enable polling for connectors which had HPD IRQ storms */ intel_hpd_irq_storm_switch_to_polling(dev_priv); @@ -539,11 +583,13 @@ static void i915_hotplug_work_func(struct work_struct *work) void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 pin_mask, u32 long_mask) { + struct intel_display *display = to_intel_display(&dev_priv->drm); struct intel_encoder *encoder; bool storm_detected = false; bool queue_dig = false, queue_hp = false; u32 long_hpd_pulse_mask = 0; u32 short_hpd_pulse_mask = 0; + u32 blocked_hpd_pins; enum hpd_pin pin; if (!pin_mask) @@ -551,6 +597,8 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, spin_lock(&dev_priv->irq_lock); + blocked_hpd_pins = get_blocked_hpd_pins(display); + /* * Determine whether ->hpd_pulse() exists for each pin, and * whether we have a short or a long pulse. This is needed @@ -573,7 +621,9 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, "digital hpd on [ENCODER:%d:%s] - %s\n", encoder->base.base.id, encoder->base.name, long_hpd ? "long" : "short"); - queue_dig = true; + + if (!(BIT(pin) & blocked_hpd_pins)) + queue_dig = true; if (long_hpd) { long_hpd_pulse_mask |= BIT(pin); @@ -617,7 +667,9 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, } else { dev_priv->display.hotplug.event_bits |= BIT(pin); long_hpd = true; - queue_hp = true; + + if (!(BIT(pin) & blocked_hpd_pins)) + queue_hp = true; } if (intel_hpd_irq_storm_detect(dev_priv, pin, long_hpd)) { @@ -915,11 +967,15 @@ static bool cancel_all_detection_work(struct drm_i915_private *i915) void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) { + struct intel_display *display = to_intel_display(&dev_priv->drm); + if (!HAS_DISPLAY(dev_priv)) return; spin_lock_irq(&dev_priv->irq_lock); + drm_WARN_ON(display->drm, get_blocked_hpd_pins(display)); + dev_priv->display.hotplug.long_hpd_pin_mask = 0; dev_priv->display.hotplug.short_hpd_pin_mask = 0; dev_priv->display.hotplug.event_bits = 0; @@ -966,19 +1022,22 @@ void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin) static void queue_work_for_missed_irqs(struct drm_i915_private *i915) { - bool queue_work = false; + struct intel_display *display = to_intel_display(&i915->drm); + struct intel_hotplug *hotplug = &display->hotplug; + bool queue_hp_work = false; + u32 blocked_hpd_pins; enum hpd_pin pin; lockdep_assert_held(&i915->irq_lock); - if (i915->display.hotplug.event_bits || - i915->display.hotplug.retry_bits) - queue_work = true; + blocked_hpd_pins = get_blocked_hpd_pins(display); + if ((hotplug->event_bits | hotplug->retry_bits) & ~blocked_hpd_pins) + queue_hp_work = true; for_each_hpd_pin(pin) { switch (i915->display.hotplug.stats[pin].state) { case HPD_MARK_DISABLED: - queue_work = true; + queue_hp_work = true; break; case HPD_DISABLED: case HPD_ENABLED: @@ -988,10 +1047,106 @@ static void queue_work_for_missed_irqs(struct drm_i915_private *i915) } } - if (queue_work) + if ((hotplug->long_hpd_pin_mask | hotplug->short_hpd_pin_mask) & ~blocked_hpd_pins) + queue_work(hotplug->dp_wq, &hotplug->dig_port_work); + + if (queue_hp_work) queue_delayed_detection_work(i915, &i915->display.hotplug.hotplug_work, 0); } +static bool block_hpd_pin(struct intel_display *display, enum hpd_pin pin) +{ + struct drm_i915_private *i915 = to_i915(display->drm); + struct intel_hotplug *hotplug = &display->hotplug; + + lockdep_assert_held(&i915->irq_lock); + + hotplug->stats[pin].blocked_count++; + + return hotplug->stats[pin].blocked_count == 1; +} + +static bool unblock_hpd_pin(struct intel_display *display, enum hpd_pin pin) +{ + struct drm_i915_private *i915 = to_i915(display->drm); + struct intel_hotplug *hotplug = &display->hotplug; + + lockdep_assert_held(&i915->irq_lock); + + drm_WARN_ON(display->drm, hotplug->stats[pin].blocked_count == 0); + hotplug->stats[pin].blocked_count--; + + return hotplug->stats[pin].blocked_count == 0; +} + +/** + * intel_hpd_block - Block handling of HPD IRQs on an HPD pin + * @encoder: Encoder to block the HPD handling for + * + * Blocks the handling of HPD IRQs on the HPD pin of @encoder. + * + * On return: + * - It's guaranteed that the blocked encoders' HPD pulse handler + * (via intel_digital_port::hpd_pulse()) is not running. + * - The hotplug event handling (via intel_encoder::hotplug()) of an + * HPD IRQ pending at the time this function is called may be still + * running. + * - Detection on the encoder's connector (via + * drm_connector_helper_funcs::detect_ctx(), + * drm_connector_funcs::detect()) remains allowed, for instance as part of + * userspace connector probing, or DRM core's connector polling. + * + * The call must be followed by calling intel_hpd_unblock(). + * + * Note that the handling of HPD IRQs for another encoder using the same HPD + * pin as that of @encoder will be also blocked. + */ +void intel_hpd_block(struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(encoder); + struct drm_i915_private *i915 = to_i915(display->drm); + struct intel_hotplug *hotplug = &display->hotplug; + bool do_flush = false; + + if (encoder->hpd_pin == HPD_NONE) + return; + + spin_lock_irq(&i915->irq_lock); + + if (block_hpd_pin(display, encoder->hpd_pin)) + do_flush = true; + + spin_unlock_irq(&i915->irq_lock); + + if (do_flush && hpd_pin_has_pulse(display, encoder->hpd_pin)) + flush_work(&hotplug->dig_port_work); +} + +/** + * intel_hpd_unblock - Unblock handling of HPD IRQs on an HPD pin + * @encoder: Encoder to unblock the HPD handling for + * + * Unblock the handling of HPD IRQs on the HPD pin of @encoder, which was + * previously blocked by intel_hpd_block(). Any HPD IRQ raised on the + * HPD pin while it was blocked will be handled for @encoder and for any + * other encoder sharing the same HPD pin. + */ +void intel_hpd_unblock(struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(encoder); + struct drm_i915_private *i915 = to_i915(display->drm); + + if (encoder->hpd_pin == HPD_NONE) + return; + + spin_lock_irq(&i915->irq_lock); + + if (unblock_hpd_pin(display, encoder->hpd_pin)) + queue_work_for_missed_irqs(i915); + + spin_unlock_irq(&i915->irq_lock); +} + void intel_hpd_enable_detection_work(struct drm_i915_private *i915) { spin_lock_irq(&i915->irq_lock); diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.h b/drivers/gpu/drm/i915/display/intel_hotplug.h index d6986902b0545..5f9857136f5e3 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.h +++ b/drivers/gpu/drm/i915/display/intel_hotplug.h @@ -28,6 +28,8 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv); enum hpd_pin intel_hpd_pin_default(enum port port); bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin); void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin); +void intel_hpd_block(struct intel_encoder *encoder); +void intel_hpd_unblock(struct intel_encoder *encoder); void intel_hpd_debugfs_register(struct drm_i915_private *i915); void intel_hpd_enable_detection_work(struct drm_i915_private *i915); From patchwork Tue Mar 4 15:29:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Imre Deak X-Patchwork-Id: 14000960 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8738DC282DC for ; Tue, 4 Mar 2025 15:29:29 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2281D10E624; Tue, 4 Mar 2025 15:29:29 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="ReBgj+dN"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by gabe.freedesktop.org (Postfix) with ESMTPS id 90E4710E61B; Tue, 4 Mar 2025 15:29:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741102167; x=1772638167; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=m4g8JgaZj/lq5XLMYbWvetVFA30K1lFJHiE16rIdRCw=; b=ReBgj+dN1Nh0uuYtJmKFlos/o5F7G7SvYTT7tp5kFEBMU9cIPl22j7fQ BwnsdLTK7H9SzeuqC10eV0gUtyTjs8dhfVLFwbxaOaijGB6JeqG+Goeji AjeJvW7bHoOGlJ7bruTXL0TGfUI8W9B9nBoJ7SEzoarDS44Dnckrg6AuF bDxZ5/mSjvXqI6F68nleCvcWmEJvgZeVldZeRz4ilo5b1OAknCHwGZTvn H/xT9YU1dS8m9mQ5I917QIW2/9tPvAgDmKqweJcd7TI2jolhT6u5dakxf nf4PiWuni2+NFzJZR9UtRVQHvHUqqUeTf9WRx2thP1i+Xz8RVcSVsmYW/ A==; X-CSE-ConnectionGUID: dYDGIcVNRLepWflmI7Xzqw== X-CSE-MsgGUID: N1Au6RvpSyqBdtg2kjQzwA== X-IronPort-AV: E=McAfee;i="6700,10204,11363"; a="59575825" X-IronPort-AV: E=Sophos;i="6.14,220,1736841600"; d="scan'208";a="59575825" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:27 -0800 X-CSE-ConnectionGUID: DRbfJvBLR36Xgb3paNcFJg== X-CSE-MsgGUID: DaIxE69OT7e9ZnAGYt5mKw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118921360" Received: from ideak-desk.fi.intel.com ([10.237.72.78]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:26 -0800 From: Imre Deak To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org Subject: [PATCH v5 4/6] drm/i915/dp: Fix link training interrupted by a short HPD pulse Date: Tue, 4 Mar 2025 17:29:15 +0200 Message-ID: <20250304152917.3407080-5-imre.deak@intel.com> X-Mailer: git-send-email 2.44.2 In-Reply-To: <20250304152917.3407080-1-imre.deak@intel.com> References: <20250304152917.3407080-1-imre.deak@intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" During Display Port link training the handling of HPD pulses should be prevented, as that handling can interfere with the link training: - Accessing DPCD registers outside the range of link training registers are not allowed by the Standard (see DP Standard v2.1, 3.5.2.16.1, 3.6.6.1). The pulse handler reads the DPRX capability registers, which are outside of the allowed range. - Switching of the LTTPR transparent/non-transparent mode may reset the LTTPRs on the link, thus aborting any ongoing link training. The pulse handler does set the LTTPR mode, thus it could unexpectedly abort the ongoing link training. Block/unblock the HPD pulse handling for the duration of the link training to prevent the above DPCD register accesses / LTTPR mode change. Apart from the above scenarios, there are other ways a non-link training DPCD register could be accessed during link training: via the DRM AUX device node, or via DPCD register probing (as performed by drm_dp_dpcd_probe()). These will be addressed by a follow-up change. v2: Rebase on the intel_hpd_suspend/resume -> intel_hpd_block/unblock() rename change. Signed-off-by: Imre Deak Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 2966f5b393922..3906c11acc968 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -1110,6 +1110,8 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp, void intel_dp_stop_link_train(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + intel_dp->link_trained = true; intel_dp_disable_dpcd_training_pattern(intel_dp, DP_PHY_DPRX); @@ -1120,6 +1122,8 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp, wait_for(intel_dp_128b132b_intra_hop(intel_dp, crtc_state) == 0, 500)) { lt_dbg(intel_dp, DP_PHY_DPRX, "128b/132b intra-hop not clearing\n"); } + + intel_hpd_unblock(encoder); } static bool @@ -1602,7 +1606,11 @@ void intel_dp_start_link_train(struct intel_atomic_state *state, * non-transparent mode. During an earlier LTTPR detection this * could've been prevented by an active link. */ - int lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp); + int lttpr_count; + + intel_hpd_block(encoder); + + lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp); if (lttpr_count < 0) /* Still continue with enabling the port and link training. */ From patchwork Tue Mar 4 15:29:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Imre Deak X-Patchwork-Id: 14000961 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1DB7BC282E5 for ; Tue, 4 Mar 2025 15:29:31 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id ADF9410E629; Tue, 4 Mar 2025 15:29:30 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="hXOmKNzf"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0F1FA10E622; Tue, 4 Mar 2025 15:29:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741102169; x=1772638169; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=7FiWaUuRURsnANGYzKdtTxj3PracIRdqjP9pZaRz89s=; b=hXOmKNzf7PPT/+PH07wGCj77SL900ZPimRKUdD4p2oYTY/O5rkct2CLq 1XGQBoXJndf0Sgothx4wmjxkI3NRAUXL2jEGD4KEHRlQYaQZYyo9A9SkE FoF48fab7BcBL1eRhDWLTfWPlk0H4q/Onwg7WAbpAk2rvSLw4FcIldddM Gg1gNw/edMCSXixTc7RXTZB4lgGMoE3ARwicg3oDR+j747Eqj05qKUBIn V+X9YNiieVz0nPT8lEyTCMzbGKbjoDc5D+G3xa0Dy8NDoCasvOsVnxCNz xQcLNH5KoNNFoNge5+93AR+VPZ2DEOuHp+vi9lr3SG5STsYUrWYgOxdil g==; X-CSE-ConnectionGUID: K6P1nfQ0S2iCt0U8ewbAOQ== X-CSE-MsgGUID: aTPRI2c+T52ij6FE0Ul1bA== X-IronPort-AV: E=McAfee;i="6700,10204,11363"; a="59575830" X-IronPort-AV: E=Sophos;i="6.14,220,1736841600"; d="scan'208";a="59575830" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:28 -0800 X-CSE-ConnectionGUID: wOPZF/JeTPGElU2esoDirw== X-CSE-MsgGUID: nUlgYJr0Rpm4rF5KNcZBTg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118921364" Received: from ideak-desk.fi.intel.com ([10.237.72.78]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:27 -0800 From: Imre Deak To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org Subject: [PATCH v5 5/6] drm/i915/dp: Queue a link check after link training is complete Date: Tue, 4 Mar 2025 17:29:16 +0200 Message-ID: <20250304152917.3407080-6-imre.deak@intel.com> X-Mailer: git-send-email 2.44.2 In-Reply-To: <20250304152917.3407080-1-imre.deak@intel.com> References: <20250304152917.3407080-1-imre.deak@intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" After link training - both in case of a passing and failing LT result - a work is scheduled to check the link state. This check should take place after the link training is completed by disabling the link training pattern and setting intel_dp::link_trained=true. Atm, the work is scheduled before these steps, which may result in checking the link state too early (and thus not retraining the link as expected). Fix the above by scheduling the link check work after link training is complete. Signed-off-by: Imre Deak Reviewed-by: Jani Nikula --- .../gpu/drm/i915/display/intel_dp_link_training.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 3906c11acc968..c1be073b9fc48 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -1110,6 +1110,7 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp, void intel_dp_stop_link_train(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(intel_dp); struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; intel_dp->link_trained = true; @@ -1124,6 +1125,13 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp, } intel_hpd_unblock(encoder); + + if (!display->hotplug.ignore_long_hpd && + intel_dp->link.seq_train_failures < 2) { + int delay_ms = intel_dp->link.seq_train_failures ? 0 : 2000; + + intel_encoder_link_check_queue_work(encoder, delay_ms); + } } static bool @@ -1628,7 +1636,6 @@ void intel_dp_start_link_train(struct intel_atomic_state *state, lt_dbg(intel_dp, DP_PHY_DPRX, "Forcing link training failure\n"); } else if (passed) { intel_dp->link.seq_train_failures = 0; - intel_encoder_link_check_queue_work(encoder, 2000); return; } @@ -1651,10 +1658,8 @@ void intel_dp_start_link_train(struct intel_atomic_state *state, return; } - if (intel_dp->link.seq_train_failures < 2) { - intel_encoder_link_check_queue_work(encoder, 0); + if (intel_dp->link.seq_train_failures < 2) return; - } if (intel_dp_schedule_fallback_link_training(state, intel_dp, crtc_state)) return; From patchwork Tue Mar 4 15:29:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Imre Deak X-Patchwork-Id: 14000962 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CBC18C021B8 for ; Tue, 4 Mar 2025 15:29:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 77E8C10E627; Tue, 4 Mar 2025 15:29:32 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="cTpaO0s3"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by gabe.freedesktop.org (Postfix) with ESMTPS id 19A4210E628; Tue, 4 Mar 2025 15:29:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741102171; x=1772638171; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HVNAhm4NMmrSddXF1R3CJWieK420v6L7rj5Jid5jbBs=; b=cTpaO0s3dUfeHqkCSjKGMX/xZzzPzcBySvLuLFyXAub4j0jQL+za8/lw ciZwSQMqK0CxRVd2TrssVLhnphii6ZOJQgtGDdqb7zqBM+lCgy180X1y0 x0as75TXhgh2B70p99urULdnSTzYn2BadB1NF9V0sYIKuW/W2Kr5FNj/3 HmehutSMtgbqf1O40tN17Z2ugT4xR4eXrxb3I1yJPXkglhg8gOwD+429k rR9TKovg3AGlhxq2X/FNzypqImFEMJmw9q/KYhcWy+jER903kjwjcjyGM C3HWeO7HN2VzbPqT73QyLOCvbjczdmD7bGuH+MDRIcjIV3ChHUIPG1HXE g==; X-CSE-ConnectionGUID: GziRfvn4RuSTIWjEb3Ta1w== X-CSE-MsgGUID: bPX7hodURhimvHAf2C4pIA== X-IronPort-AV: E=McAfee;i="6700,10204,11363"; a="59575844" X-IronPort-AV: E=Sophos;i="6.14,220,1736841600"; d="scan'208";a="59575844" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:30 -0800 X-CSE-ConnectionGUID: aVrK8f53QhyYsBCIzdJ2YQ== X-CSE-MsgGUID: W9TCAQodTme//Z03DfrtIg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118921368" Received: from ideak-desk.fi.intel.com ([10.237.72.78]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Mar 2025 07:29:28 -0800 From: Imre Deak To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org Cc: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= Subject: [PATCH v5 6/6] drm/i915/crt: Use intel_hpd_block/unblock() instead of intel_hpd_disable/enable() Date: Tue, 4 Mar 2025 17:29:17 +0200 Message-ID: <20250304152917.3407080-7-imre.deak@intel.com> X-Mailer: git-send-email 2.44.2 In-Reply-To: <20250304152917.3407080-1-imre.deak@intel.com> References: <20250304152917.3407080-1-imre.deak@intel.com> MIME-Version: 1.0 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" intel_hpd_disable/enable() have the same purpose as intel_hpd_block/unblock(), except that disable/enable will drop any HPD IRQs which were triggered while the HPD was disabled, while block/unblock will handle such IRQs after the IRQ handling is unblocked. Use intel_hpd_block/unblock() for crt as well, by adding a helper to explicitly clear any pending IRQs before unblocking. v2: - Handle encoders without a port assigned to them. - Rebase on change in intel_hpd_suspend() documentation. v3: - Rebase on the suspend/resume -> block/unblock rename change. - Clear the pending events only after all encoders have unblocked the HPD handling. - Clear the short/long port events for all encoders using the given HPD pin. v4: - Rebase on port->hpd_pin tracking. (Ville) Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_crt.c | 7 +-- drivers/gpu/drm/i915/display/intel_hotplug.c | 60 +++++++++++--------- drivers/gpu/drm/i915/display/intel_hotplug.h | 3 +- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 76ffb3f8467c8..bca91d49cb960 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -532,8 +532,6 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) { struct intel_display *display = to_intel_display(connector->dev); struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector)); - struct drm_i915_private *dev_priv = to_i915(connector->dev); - bool reenable_hpd; u32 adpa; bool ret; u32 save_adpa; @@ -550,7 +548,7 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) * * Just disable HPD interrupts here to prevent this */ - reenable_hpd = intel_hpd_disable(dev_priv, crt->base.hpd_pin); + intel_hpd_block(&crt->base); save_adpa = adpa = intel_de_read(display, crt->adpa_reg); drm_dbg_kms(display->drm, @@ -577,8 +575,7 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) drm_dbg_kms(display->drm, "valleyview hotplug adpa=0x%x, result %d\n", adpa, ret); - if (reenable_hpd) - intel_hpd_enable(dev_priv, crt->base.hpd_pin); + intel_hpd_clear_and_unblock(&crt->base); return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index cb4e320a1023d..423925fec73dc 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -993,33 +993,6 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "Hotplug detection work still active\n"); } -bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin) -{ - bool ret = false; - - if (pin == HPD_NONE) - return false; - - spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display.hotplug.stats[pin].state == HPD_ENABLED) { - dev_priv->display.hotplug.stats[pin].state = HPD_DISABLED; - ret = true; - } - spin_unlock_irq(&dev_priv->irq_lock); - - return ret; -} - -void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin) -{ - if (pin == HPD_NONE) - return; - - spin_lock_irq(&dev_priv->irq_lock); - dev_priv->display.hotplug.stats[pin].state = HPD_ENABLED; - spin_unlock_irq(&dev_priv->irq_lock); -} - static void queue_work_for_missed_irqs(struct drm_i915_private *i915) { struct intel_display *display = to_intel_display(&i915->drm); @@ -1096,7 +1069,8 @@ static bool unblock_hpd_pin(struct intel_display *display, enum hpd_pin pin) * drm_connector_funcs::detect()) remains allowed, for instance as part of * userspace connector probing, or DRM core's connector polling. * - * The call must be followed by calling intel_hpd_unblock(). + * The call must be followed by calling intel_hpd_unblock(), or + * intel_hpd_clear_and_unblock(). * * Note that the handling of HPD IRQs for another encoder using the same HPD * pin as that of @encoder will be also blocked. @@ -1147,6 +1121,36 @@ void intel_hpd_unblock(struct intel_encoder *encoder) spin_unlock_irq(&i915->irq_lock); } +/** + * intel_hpd_clear_and_unblock - Unblock handling of new HPD IRQs on an HPD pin + * @encoder: Encoder to unblock the HPD handling for + * + * Unblock the handling of HPD IRQs on the HPD pin of @encoder, which was + * previously blocked by intel_hpd_block(). Any HPD IRQ raised on the + * HPD pin while it was blocked will be cleared, handling only new IRQs. + */ +void intel_hpd_clear_and_unblock(struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(encoder); + struct drm_i915_private *i915 = to_i915(display->drm); + struct intel_hotplug *hotplug = &display->hotplug; + enum hpd_pin pin = encoder->hpd_pin; + + if (pin == HPD_NONE) + return; + + spin_lock_irq(&i915->irq_lock); + + if (unblock_hpd_pin(display, pin)) { + hotplug->event_bits &= ~BIT(pin); + hotplug->retry_bits &= ~BIT(pin); + hotplug->short_hpd_pin_mask &= ~BIT(pin); + hotplug->long_hpd_pin_mask &= ~BIT(pin); + } + + spin_unlock_irq(&i915->irq_lock); +} + void intel_hpd_enable_detection_work(struct drm_i915_private *i915) { spin_lock_irq(&i915->irq_lock); diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.h b/drivers/gpu/drm/i915/display/intel_hotplug.h index 5f9857136f5e3..f189b871904ed 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.h +++ b/drivers/gpu/drm/i915/display/intel_hotplug.h @@ -26,10 +26,9 @@ void intel_hpd_init(struct drm_i915_private *dev_priv); void intel_hpd_init_early(struct drm_i915_private *i915); void intel_hpd_cancel_work(struct drm_i915_private *dev_priv); enum hpd_pin intel_hpd_pin_default(enum port port); -bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin); -void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin); void intel_hpd_block(struct intel_encoder *encoder); void intel_hpd_unblock(struct intel_encoder *encoder); +void intel_hpd_clear_and_unblock(struct intel_encoder *encoder); void intel_hpd_debugfs_register(struct drm_i915_private *i915); void intel_hpd_enable_detection_work(struct drm_i915_private *i915);