From patchwork Fri Jun 27 15:19:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 4436081 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 5F09F9F383 for ; Fri, 27 Jun 2014 15:24:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 72B9720172 for ; Fri, 27 Jun 2014 15:24:55 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 82955200F4 for ; Fri, 27 Jun 2014 15:24:54 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1X0Xyk-0002mk-ND; Fri, 27 Jun 2014 15:22:18 +0000 Received: from mail-we0-x22b.google.com ([2a00:1450:400c:c03::22b]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X0XwO-0008Jp-HN for linux-arm-kernel@lists.infradead.org; Fri, 27 Jun 2014 15:19:53 +0000 Received: by mail-we0-f171.google.com with SMTP id q58so5460628wes.30 for ; Fri, 27 Jun 2014 08:19:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=TrW8EqaI/faPBggLVh1EqYep8VfTpyTKPF/n7G++WzM=; b=x5FwHERk3W4j7/gfTMY9SUPOHTh3hCiRdEhCGgvzxP5D7Jspn/cGDbmi/c4ruj1ZcZ DXLRWAzjJful0qgE1+kPoksnpUN0lgzs5ABCPL1xg5UcET42Yytx1sSPr4K3N3iJsR23 H2Czx9iP93XBnT1LKaFHz4bRLx09IDL7KutO+nAFcw8H87d8p7UZCc2j8uRijzJh8eTE 6n5jMoRUQ12wXAf7kHQ+SMtOc/jGiwM9voOBy7YsNEWrk84e5GOsGYLPXYEQBaaNmiUw 6iX0dBpGDO00GylRA016i4R8N03sOggnStYYaerpKeqRURvVdexPMP3pQzMPH7RevLZ6 uzfA== X-Received: by 10.194.133.67 with SMTP id pa3mr3128452wjb.134.1403882367833; Fri, 27 Jun 2014 08:19:27 -0700 (PDT) Received: from localhost (port-35906.pppoe.wtnet.de. [46.59.191.32]) by mx.google.com with ESMTPSA id ex4sm78963905wic.2.2014.06.27.08.19.26 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Jun 2014 08:19:27 -0700 (PDT) From: Thierry Reding To: dri-devel@lists.freedesktop.org Subject: [PATCH v3 1/4] drm/fb-helper: Fix hpd vs. initial config races Date: Fri, 27 Jun 2014 17:19:22 +0200 Message-Id: <1403882365-18337-1-git-send-email-thierry.reding@gmail.com> X-Mailer: git-send-email 2.0.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140627_081952_849050_0772DA49 X-CRM114-Status: GOOD ( 18.15 ) X-Spam-Score: -0.8 (/) Cc: linux-samsung-soc@vger.kernel.org, Daniel Vetter , Imre Deak , linux-tegra@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Daniel Vetter Some drivers need to be able to have a perfect race-free fbcon setup. Current drivers only enable hotplug processing after the call to drm_fb_helper_initial_config which leaves a tiny but important race. This race is especially noticable on embedded platforms where the driver itself enables the voltage for the hdmi output, since only then will monitors (after a bit of delay, as usual) respond by asserting the hpd pin. Most of the infrastructure is already there with the split-out drm_fb_helper_init. And drm_fb_helper_initial_config already has all the required locking to handle concurrent hpd events since commit 53f1904bced78d7c00f5d874c662ec3ac85d0f9f Author: Daniel Vetter Date: Thu Mar 20 14:26:35 2014 +0100 drm/fb-helper: improve drm_fb_helper_initial_config locking The only missing bit is making drm_fb_helper_hotplug_event save against concurrent calls of drm_fb_helper_initial_config. The only unprotected bit is the check for fb_helper->fb. With that drivers can first initialize the fb helper, then enabel hotplug processing and then set up the initial config all in a completely race-free manner. Update kerneldoc and convert i915 as a proof of concept. Feature requested by Thierry since his tegra driver atm reliably boots slowly enough to misses the hotplug event for an external hdmi screen, but also reliably boots to quickly for the hpd pin to be asserted when the fb helper calls into the hdmi ->detect function. Cc: Thierry Reding Signed-off-by: Daniel Vetter Signed-off-by: Thierry Reding --- Changes in v3: - remove an additional occurrence of i915's enable_hotplug_processing that was introduced after the original patch drivers/gpu/drm/drm_fb_helper.c | 11 +++++------ drivers/gpu/drm/i915/i915_dma.c | 3 --- drivers/gpu/drm/i915/i915_drv.c | 2 -- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_irq.c | 4 ---- 5 files changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d5d8cea1a679..13a098c9af31 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1613,8 +1613,10 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); * either the output polling work or a work item launched from the driver's * hotplug interrupt). * - * Note that the driver must ensure that this is only called _after_ the fb has - * been fully set up, i.e. after the call to drm_fb_helper_initial_config. + * Note that drivers may call this even before calling + * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows + * for a race-free fbcon setup and will make sure that the fbdev emulation will + * not miss any hotplug events. * * RETURNS: * 0 on success and a non-zero error code otherwise. @@ -1624,11 +1626,8 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) struct drm_device *dev = fb_helper->dev; u32 max_width, max_height; - if (!fb_helper->fb) - return 0; - mutex_lock(&fb_helper->dev->mode_config.mutex); - if (!drm_fb_helper_is_bound(fb_helper)) { + if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { fb_helper->delayed_hotplug = true; mutex_unlock(&fb_helper->dev->mode_config.mutex); return 0; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5e583a1838f8..84b55665bd87 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1377,9 +1377,6 @@ static int i915_load_modeset_init(struct drm_device *dev) */ intel_fbdev_initial_config(dev); - /* Only enable hotplug handling once the fbdev is fully set up. */ - dev_priv->enable_hotplug_processing = true; - drm_kms_helper_poll_init(dev); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6eb45ac7a7d5..b0955fffca98 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -521,7 +521,6 @@ static int i915_drm_freeze(struct drm_device *dev) } intel_runtime_pm_disable_interrupts(dev); - dev_priv->enable_hotplug_processing = false; intel_suspend_gt_powersave(dev); @@ -659,7 +658,6 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) * notifications. * */ intel_hpd_init(dev); - dev_priv->enable_hotplug_processing = true; /* Config may have changed between suspend and resume */ drm_helper_hpd_irq_event(dev); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8cea59649ef2..df6a98cd702f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1404,7 +1404,6 @@ struct drm_i915_private { u32 pipestat_irq_mask[I915_MAX_PIPES]; struct work_struct hotplug_work; - bool enable_hotplug_processing; struct { unsigned long hpd_last_jiffies; int hpd_cnt; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1c1ec22bc7ef..c0d7674c45cd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1109,10 +1109,6 @@ static void i915_hotplug_work_func(struct work_struct *work) bool changed = false; u32 hpd_event_bits; - /* HPD irq before everything is fully set up. */ - if (!dev_priv->enable_hotplug_processing) - return; - mutex_lock(&mode_config->mutex); DRM_DEBUG_KMS("running encoder hotplug functions\n");