From patchwork Tue Jul 23 07:38:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: You-Sheng Yang X-Patchwork-Id: 1135456 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45t9Mk5LQTz9sDB; Tue, 23 Jul 2019 17:38:58 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1hppNv-00052z-8J; Tue, 23 Jul 2019 07:38:55 +0000 Received: from mail-pg1-f196.google.com ([209.85.215.196]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1hppNs-00051q-DC for kernel-team@lists.ubuntu.com; Tue, 23 Jul 2019 07:38:52 +0000 Received: by mail-pg1-f196.google.com with SMTP id n9so12763338pgc.1 for ; Tue, 23 Jul 2019 00:38:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=sJxV1Of7d+CJHYcz6hakExDq+LTJgsQTJI8rXYVj19A=; b=B6H2O8aCBMdCgmmVXLnnnac4xz+CZH+rpyBtVWgyiMewD5f7mItJRzAzTP5Uk7j1Vc 0zBR4Rt0DwHgXE4tDkpDRvvJLqizxToR0V6bE9ZcS3MZbpmoE2hIs+qG+3tsP7JBn182 EXa4R53gv0flmJ1wAhWIgD5JWgOLfK3V4M+0kN8VI6of2X1mMBL4dkNhkgQErOecfSzi aug0Tca2iMUUyCItMIFXWT9z6+nbxkvUCi+5ViIkYR6cwAYHoK76yDMDmJopPSPhMpEb 11wqbzkGVi8svwVbMBXtSlNylGhyu23KMLlfwrFMTaIDf8QJAOLsFbF5Rd/xQH7e5tcy s6GQ== X-Gm-Message-State: APjAAAW3VqdzRW4+o69tlg9KuSWNF0ZO8gEa6Y2RQDjwIW3AoQR7z5RR OI1vsInmcODeVQB+9dddUrI0OkGz X-Google-Smtp-Source: APXvYqxH23KSXaNGpTJvQR2ZpbMxX4w1GPQExTKVtpczjKiAekQc8oM/vfpuQnZ3V2p97r6Z6TOfbQ== X-Received: by 2002:a63:4522:: with SMTP id s34mr74719846pga.362.1563867530586; Tue, 23 Jul 2019 00:38:50 -0700 (PDT) Received: from momoga.taipei.internal (61-220-137-37.HINET-IP.hinet.net. [61.220.137.37]) by smtp.gmail.com with ESMTPSA id y10sm43162570pfm.66.2019.07.23.00.38.49 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 23 Jul 2019 00:38:50 -0700 (PDT) From: You-Sheng Yang To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/2][SRU][C] drm/i915: Add support for retrying hotplug Date: Tue, 23 Jul 2019 15:38:44 +0800 Message-Id: <20190723073845.21842-2-vicamo.yang@canonical.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190723073845.21842-1-vicamo.yang@canonical.com> References: <20190723073845.21842-1-vicamo.yang@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Imre Deak BugLink: http://bugs.launchpad.net/bugs/1835001 There is some scenarios that we are aware that sink probe can fail, so lets add the infrastructure to let hotplug() hook to request another probe after some time. v2: Handle shared HPD pins (Imre) v3: Rebased v4: Renamed INTEL_HOTPLUG_NOCHANGE to INTEL_HOTPLUG_UNCHANGED to keep it consistent(Rodrigo) v5: Making the working queue used explicit through all the callers to hotplug_work (Ville) Tested-by: Timo Aaltonen Cc: Ville Syrjälä Reviewed-by: Rodrigo Vivi Signed-off-by: José Roberto de Souza Signed-off-by: Jani Nikula Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20190712005343.24571-1-jose.souza@intel.com (backported from commit 3944709df8e9298225fc2b29e53ee8e6f4b26618 git://anongit.freedesktop.org/drm-intel) Signed-off-by: You-Sheng Yang --- drivers/gpu/drm/i915/i915_debugfs.c | 2 + drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/intel_ddi.c | 12 +++--- drivers/gpu/drm/i915/intel_dp.c | 12 +++--- drivers/gpu/drm/i915/intel_drv.h | 16 ++++++-- drivers/gpu/drm/i915/intel_hotplug.c | 59 ++++++++++++++++++++++------ drivers/gpu/drm/i915/intel_sdvo.c | 8 ++-- 7 files changed, 81 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 13e7b9e4a6e6..8bad1f2a87d4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4591,6 +4591,8 @@ static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = m->private; struct i915_hotplug *hotplug = &dev_priv->hotplug; + flush_delayed_work(&dev_priv->hotplug.hotplug_work); + seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold); seq_printf(m, "Detected: %s\n", yesno(delayed_work_pending(&hotplug->reenable_work))); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 70a54f77dd4b..409deda2e095 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -273,7 +273,7 @@ enum hpd_pin { #define HPD_STORM_DEFAULT_THRESHOLD 5 struct i915_hotplug { - struct work_struct hotplug_work; + struct delayed_work hotplug_work; struct { unsigned long last_jiffies; @@ -285,6 +285,7 @@ struct i915_hotplug { } state; } stats[HPD_NUM_PINS]; u32 event_bits; + u32 retry_bits; struct delayed_work reenable_work; struct intel_digital_port *irq_port[I915_MAX_PORTS]; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e195c287c263..2161ce3dc82e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3334,14 +3334,16 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder, return modeset_pipe(&crtc->base, ctx); } -static bool intel_ddi_hotplug(struct intel_encoder *encoder, - struct intel_connector *connector) +static enum intel_hotplug_state +intel_ddi_hotplug(struct intel_encoder *encoder, + struct intel_connector *connector, + bool irq_received) { struct drm_modeset_acquire_ctx ctx; - bool changed; + enum intel_hotplug_state state; int ret; - changed = intel_encoder_hotplug(encoder, connector); + state = intel_encoder_hotplug(encoder, connector, irq_received); drm_modeset_acquire_init(&ctx, 0); @@ -3363,7 +3365,7 @@ static bool intel_ddi_hotplug(struct intel_encoder *encoder, drm_modeset_acquire_fini(&ctx); WARN(ret, "Acquiring modeset locks failed with %i\n", ret); - return changed; + return state; } static struct intel_connector * diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5d6517d37236..ce6e1f3747af 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4400,14 +4400,16 @@ int intel_dp_retrain_link(struct intel_encoder *encoder, * retrain the link to get a picture. That's in case no * userspace component reacted to intermittent HPD dip. */ -static bool intel_dp_hotplug(struct intel_encoder *encoder, - struct intel_connector *connector) +static enum intel_hotplug_state +intel_dp_hotplug(struct intel_encoder *encoder, + struct intel_connector *connector, + bool irq_received) { struct drm_modeset_acquire_ctx ctx; - bool changed; + enum intel_hotplug_state state; int ret; - changed = intel_encoder_hotplug(encoder, connector); + state = intel_encoder_hotplug(encoder, connector, irq_received); drm_modeset_acquire_init(&ctx, 0); @@ -4426,7 +4428,7 @@ static bool intel_dp_hotplug(struct intel_encoder *encoder, drm_modeset_acquire_fini(&ctx); WARN(ret, "Acquiring modeset locks failed with %i\n", ret); - return changed; + return state; } /* diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 030b0ffe8fdf..a34c3d6b5850 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -217,14 +217,21 @@ struct intel_fbdev { int preferred_bpp; }; +enum intel_hotplug_state { + INTEL_HOTPLUG_UNCHANGED, + INTEL_HOTPLUG_CHANGED, + INTEL_HOTPLUG_RETRY, +}; + struct intel_encoder { struct drm_encoder base; enum intel_output_type type; enum port port; unsigned int cloneable; - bool (*hotplug)(struct intel_encoder *encoder, - struct intel_connector *connector); + enum intel_hotplug_state (*hotplug)(struct intel_encoder *encoder, + struct intel_connector *connector, + bool irq_received); enum intel_output_type (*compute_output_type)(struct intel_encoder *, struct intel_crtc_state *, struct drm_connector_state *); @@ -1752,8 +1759,9 @@ int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector); void intel_dvo_init(struct drm_i915_private *dev_priv); /* intel_hotplug.c */ void intel_hpd_poll_init(struct drm_i915_private *dev_priv); -bool intel_encoder_hotplug(struct intel_encoder *encoder, - struct intel_connector *connector); +enum intel_hotplug_state intel_encoder_hotplug(struct intel_encoder *encoder, + struct intel_connector *connector, + bool irq_received); /* legacy fbdev emulation in intel_fbdev.c */ #ifdef CONFIG_DRM_FBDEV_EMULATION diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index 43aa92beff2a..50f2075719e1 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -143,6 +143,7 @@ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv, #define HPD_STORM_DETECT_PERIOD 1000 #define HPD_STORM_REENABLE_DELAY (2 * 60 * 1000) +#define HPD_RETRY_DELAY 1000 /** * intel_hpd_irq_storm_detect - gather stats and detect HPD irq storm on a pin @@ -277,8 +278,10 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work) intel_runtime_pm_put(dev_priv); } -bool intel_encoder_hotplug(struct intel_encoder *encoder, - struct intel_connector *connector) +enum intel_hotplug_state +intel_encoder_hotplug(struct intel_encoder *encoder, + struct intel_connector *connector, + bool irq_received) { struct drm_device *dev = connector->base.dev; enum drm_connector_status old_status; @@ -290,7 +293,7 @@ bool intel_encoder_hotplug(struct intel_encoder *encoder, drm_helper_probe_detect(&connector->base, NULL, false); if (old_status == connector->base.status) - return false; + return INTEL_HOTPLUG_UNCHANGED; DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", connector->base.base.id, @@ -298,7 +301,7 @@ bool intel_encoder_hotplug(struct intel_encoder *encoder, drm_get_connector_status_name(old_status), drm_get_connector_status_name(connector->base.status)); - return true; + return INTEL_HOTPLUG_CHANGED; } static void i915_digport_work_func(struct work_struct *work) @@ -345,7 +348,7 @@ static void i915_digport_work_func(struct work_struct *work) spin_lock_irq(&dev_priv->irq_lock); dev_priv->hotplug.event_bits |= old_bits; spin_unlock_irq(&dev_priv->irq_lock); - schedule_work(&dev_priv->hotplug.hotplug_work); + queue_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, 0); } } @@ -355,14 +358,16 @@ static void i915_digport_work_func(struct work_struct *work) static void i915_hotplug_work_func(struct work_struct *work) { struct drm_i915_private *dev_priv = - container_of(work, struct drm_i915_private, hotplug.hotplug_work); + container_of(work, struct drm_i915_private, + hotplug.hotplug_work.work); struct drm_device *dev = &dev_priv->drm; struct intel_connector *intel_connector; struct intel_encoder *intel_encoder; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; - bool changed = false; + u32 changed = 0, retry = 0; u32 hpd_event_bits; + u32 hpd_retry_bits; mutex_lock(&dev->mode_config.mutex); DRM_DEBUG_KMS("running encoder hotplug functions\n"); @@ -371,6 +376,8 @@ static void i915_hotplug_work_func(struct work_struct *work) hpd_event_bits = dev_priv->hotplug.event_bits; dev_priv->hotplug.event_bits = 0; + hpd_retry_bits = dev_priv->hotplug.retry_bits; + dev_priv->hotplug.retry_bits = 0; /* Disable hotplug on connectors that hit an irq storm. */ intel_hpd_irq_storm_disable(dev_priv); @@ -379,16 +386,29 @@ static void i915_hotplug_work_func(struct work_struct *work) drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { + u32 hpd_bit; + intel_connector = to_intel_connector(connector); if (!intel_connector->encoder) continue; intel_encoder = intel_connector->encoder; - if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) { + hpd_bit = BIT(intel_encoder->hpd_pin); + if ((hpd_event_bits | hpd_retry_bits) & hpd_bit) { DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n", connector->name, intel_encoder->hpd_pin); - changed |= intel_encoder->hotplug(intel_encoder, - intel_connector); + switch (intel_encoder->hotplug(intel_encoder, + intel_connector, + hpd_event_bits & hpd_bit)) { + case INTEL_HOTPLUG_UNCHANGED: + break; + case INTEL_HOTPLUG_CHANGED: + changed |= hpd_bit; + break; + case INTEL_HOTPLUG_RETRY: + retry |= hpd_bit; + break; + } } } drm_connector_list_iter_end(&conn_iter); @@ -396,6 +416,17 @@ static void i915_hotplug_work_func(struct work_struct *work) if (changed) drm_kms_helper_hotplug_event(dev); + + /* Remove shared HPD pins that have changed */ + retry &= ~changed; + if (retry) { + spin_lock_irq(&dev_priv->irq_lock); + dev_priv->hotplug.retry_bits |= retry; + spin_unlock_irq(&dev_priv->irq_lock); + + mod_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, + msecs_to_jiffies(HPD_RETRY_DELAY)); + } } @@ -494,7 +525,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, if (queue_dig) queue_work(dev_priv->hotplug.dp_wq, &dev_priv->hotplug.dig_port_work); if (queue_hp) - schedule_work(&dev_priv->hotplug.hotplug_work); + queue_delayed_work(system_wq, &dev_priv->hotplug.hotplug_work, 0); } /** @@ -614,7 +645,8 @@ void intel_hpd_poll_init(struct drm_i915_private *dev_priv) void intel_hpd_init_work(struct drm_i915_private *dev_priv) { - INIT_WORK(&dev_priv->hotplug.hotplug_work, i915_hotplug_work_func); + INIT_DELAYED_WORK(&dev_priv->hotplug.hotplug_work, + i915_hotplug_work_func); INIT_WORK(&dev_priv->hotplug.dig_port_work, i915_digport_work_func); INIT_WORK(&dev_priv->hotplug.poll_init_work, i915_hpd_poll_init_work); INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work, @@ -628,11 +660,12 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) dev_priv->hotplug.long_port_mask = 0; dev_priv->hotplug.short_port_mask = 0; dev_priv->hotplug.event_bits = 0; + dev_priv->hotplug.retry_bits = 0; spin_unlock_irq(&dev_priv->irq_lock); cancel_work_sync(&dev_priv->hotplug.dig_port_work); - cancel_work_sync(&dev_priv->hotplug.hotplug_work); + cancel_delayed_work_sync(&dev_priv->hotplug.hotplug_work); cancel_work_sync(&dev_priv->hotplug.poll_init_work); cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work); } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 26975df4e593..b117ef881995 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1714,12 +1714,14 @@ static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder) &intel_sdvo->hotplug_active, 2); } -static bool intel_sdvo_hotplug(struct intel_encoder *encoder, - struct intel_connector *connector) +static enum intel_hotplug_state +intel_sdvo_hotplug(struct intel_encoder *encoder, + struct intel_connector *connector, + bool irq_received) { intel_sdvo_enable_hotplug(encoder); - return intel_encoder_hotplug(encoder, connector); + return intel_encoder_hotplug(encoder, connector, irq_received); } static bool From patchwork Tue Jul 23 07:38:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: You-Sheng Yang X-Patchwork-Id: 1135457 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45t9Mp6w4Dz9sDB; Tue, 23 Jul 2019 17:39:02 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1hppNz-00054M-E5; Tue, 23 Jul 2019 07:38:59 +0000 Received: from mail-pl1-f194.google.com ([209.85.214.194]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1hppNt-00052X-Mh for kernel-team@lists.ubuntu.com; Tue, 23 Jul 2019 07:38:53 +0000 Received: by mail-pl1-f194.google.com with SMTP id ay6so20291141plb.9 for ; Tue, 23 Jul 2019 00:38:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wpyi/ndVVfPMoIgBTKSWqG9K+G65KesPCHxFUHjGC8o=; b=ogRXj5O0j/5yuBVV0D+maQ8QA01j7hdECHZ1qGo1abazSL4+2LJSeH3PKl8rgOwfMO /fMdUPOOIfC8nev2jnHmKA4248/KrsLdU4NgGnwOoOHOb18nQtCd/yGcCwkGgjKuyq0j /H//xqCdy78+VegqeVPqOLS8nWn3LLFDbG/8EhWylFzwHmMv3TBbNyp4sYycnB/5k9zG zZc1rfqORSzbhqHjO3d64Vb2pTbjxVG/B7ifwB6GJh1aDvXUZ6TowkJaRKKSjqYMej+G A/VpLn0Z41kcJwAwEQqHumzdLBQMv4H5rd+mTQO4DZ5nKg0iUQxTpLI+5xrKAlvPQrDn SwnQ== X-Gm-Message-State: APjAAAXuwgZA90eKyyooV2Brm02qQl3Cn+cFfODe6J0oDMm9euoVsefQ JRa0/KllX6zKcCeo8m+TICG+syz6 X-Google-Smtp-Source: APXvYqzf5JRDSJf+uVXnCbR7UihpH8tjJxyHrf9ydbM9wDIkYeEnZE1/Pwltps4kkFYvk1HGN0soDg== X-Received: by 2002:a17:902:1101:: with SMTP id d1mr34857449pla.212.1563867531927; Tue, 23 Jul 2019 00:38:51 -0700 (PDT) Received: from momoga.taipei.internal (61-220-137-37.HINET-IP.hinet.net. [61.220.137.37]) by smtp.gmail.com with ESMTPSA id y10sm43162570pfm.66.2019.07.23.00.38.50 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 23 Jul 2019 00:38:51 -0700 (PDT) From: You-Sheng Yang To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/2][SRU][C] drm/i915: Enable hotplug retry Date: Tue, 23 Jul 2019 15:38:45 +0800 Message-Id: <20190723073845.21842-3-vicamo.yang@canonical.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190723073845.21842-1-vicamo.yang@canonical.com> References: <20190723073845.21842-1-vicamo.yang@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: José Roberto de Souza BugLink: http://bugs.launchpad.net/bugs/1835001 Right now we are aware of two cases that needs another hotplug retry: - Unpowered type-c dongles - HDMI slow unplug Both have a complete explanation in the code to schedule another run of the hotplug handler. It could have more checks to just trigger the retry in those two specific cases but why would sink signal a long pulse if there is no change? Also the drawback of running the hotplug handler again is really low and that could fix another cases that we are not aware. Also retrying for old DP ports(non-DDI) to make it consistent and not cause CI failures if those systems are connected to chamelium boards that will be used to simulate the issues reported in here. v2: Also retrying for old DP ports(non-DDI)(Imre) v4: Renamed INTEL_HOTPLUG_NOCHANGE to INTEL_HOTPLUG_UNCHANGED to keep it consistent(Rodrigo) Tested-by: Timo Aaltonen Cc: Ville Syrjälä Cc: Imre Deak Cc: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20190712005343.24571-2-jose.souza@intel.com (backported from commit bb80c9255770fa1ed54e889a6bee628bdd0f6762 git://anongit.freedesktop.org/drm-intel) Signed-off-by: You-Sheng Yang --- drivers/gpu/drm/i915/intel_ddi.c | 21 +++++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 7 +++++++ drivers/gpu/drm/i915/intel_hdmi.c | 28 +++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 2161ce3dc82e..df5e2fb562df 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3339,6 +3339,7 @@ intel_ddi_hotplug(struct intel_encoder *encoder, struct intel_connector *connector, bool irq_received) { + struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); struct drm_modeset_acquire_ctx ctx; enum intel_hotplug_state state; int ret; @@ -3365,6 +3366,26 @@ intel_ddi_hotplug(struct intel_encoder *encoder, drm_modeset_acquire_fini(&ctx); WARN(ret, "Acquiring modeset locks failed with %i\n", ret); + /* + * Unpowered type-c dongles can take some time to boot and be + * responsible, so here giving some time to those dongles to power up + * and then retrying the probe. + * + * On many platforms the HDMI live state signal is known to be + * unreliable, so we can't use it to detect if a sink is connected or + * not. Instead we detect if it's connected based on whether we can + * read the EDID or not. That in turn has a problem during disconnect, + * since the HPD interrupt may be raised before the DDC lines get + * disconnected (due to how the required length of DDC vs. HPD + * connector pins are specified) and so we'll still be able to get a + * valid EDID. To solve this schedule another detection cycle if this + * time around we didn't detect any change in the sink's connection + * status. + */ + if (state == INTEL_HOTPLUG_UNCHANGED && irq_received && + !dig_port->dp.is_mst) + state = INTEL_HOTPLUG_RETRY; + return state; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ce6e1f3747af..346f6b368f78 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4428,6 +4428,13 @@ intel_dp_hotplug(struct intel_encoder *encoder, drm_modeset_acquire_fini(&ctx); WARN(ret, "Acquiring modeset locks failed with %i\n", ret); + /* + * Keeping it consistent with intel_ddi_hotplug() and + * intel_hdmi_hotplug(). + */ + if (state == INTEL_HOTPLUG_UNCHANGED && irq_received) + state = INTEL_HOTPLUG_RETRY; + return state; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 79eb57b9c9bf..77149f0db916 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -2367,6 +2367,32 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, } } +static enum intel_hotplug_state +intel_hdmi_hotplug(struct intel_encoder *encoder, + struct intel_connector *connector, bool irq_received) +{ + enum intel_hotplug_state state; + + state = intel_encoder_hotplug(encoder, connector, irq_received); + + /* + * On many platforms the HDMI live state signal is known to be + * unreliable, so we can't use it to detect if a sink is connected or + * not. Instead we detect if it's connected based on whether we can + * read the EDID or not. That in turn has a problem during disconnect, + * since the HPD interrupt may be raised before the DDC lines get + * disconnected (due to how the required length of DDC vs. HPD + * connector pins are specified) and so we'll still be able to get a + * valid EDID. To solve this schedule another detection cycle if this + * time around we didn't detect any change in the sink's connection + * status. + */ + if (state == INTEL_HOTPLUG_UNCHANGED && irq_received) + state = INTEL_HOTPLUG_RETRY; + + return state; +} + void intel_hdmi_init(struct drm_i915_private *dev_priv, i915_reg_t hdmi_reg, enum port port) { @@ -2390,7 +2416,7 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port)); - intel_encoder->hotplug = intel_encoder_hotplug; + intel_encoder->hotplug = intel_hdmi_hotplug; intel_encoder->compute_config = intel_hdmi_compute_config; if (HAS_PCH_SPLIT(dev_priv)) { intel_encoder->disable = pch_disable_hdmi;