From patchwork Tue Jul 4 15:18:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 9825263 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E78E660237 for ; Tue, 4 Jul 2017 15:20:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4351124B48 for ; Tue, 4 Jul 2017 15:20:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3607C27DCD; Tue, 4 Jul 2017 15:20:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4286624B48 for ; Tue, 4 Jul 2017 15:20:03 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6A87A6E389; Tue, 4 Jul 2017 15:18:58 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-x244.google.com (mail-wm0-x244.google.com [IPv6:2a00:1450:400c:c09::244]) by gabe.freedesktop.org (Postfix) with ESMTPS id 666EE6E389 for ; Tue, 4 Jul 2017 15:18:56 +0000 (UTC) Received: by mail-wm0-x244.google.com with SMTP id y5so26951193wmh.3 for ; Tue, 04 Jul 2017 08:18:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YHyJMUx0W7YnAffFhKqTn5WxoI7LY1KmtU2ma0fw7m0=; b=Y/iDMfA1kXJezXkEcOSV0fSTomVLMm7Tj99BJx5rY/PjtZCDK79J8WtYxa4MeTTIcZ bq5XusCSilRebgIvHqnfaRWNRtw2D5TrD67NA7Wm2kQwoTR4dDASGWrKuffOj5jCAVni 2tXo0wJmVKJ+r1oB6ai1to17Agu4NaUsyDHf4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YHyJMUx0W7YnAffFhKqTn5WxoI7LY1KmtU2ma0fw7m0=; b=tF4Ue8x7YA4NIRZ/pqUOVZF7tMviftewzfhnO5s34FQ1+K/dihqHOY395b7UXvxo89 /1+Hr5fQZb77OWqDUZBvR1BTd61SoGzFvU0DLrWH3VB2IyX8BWfWgYQb3YpjpPfLkp3O bsGPxGMpjWXo4RgWjHtiblUHeXusRo4DPOwG3lZihblPMNUmQDN8Q/mlIEEgJMAWQR2b wRhbreVUZOrXCaleO2rYfbWo5czuVyhDLyGSS9m0sf+gc4xVl72YjYKhKcBgVen5VEQE cpWnr8YIG2InFWRz0+rSHdHYdEyAZcrdI77GEeoUyp9xfammEfhtlQKy6paW56O1Ckum BXfg== X-Gm-Message-State: AKS2vOxNsNMfJuSU92XhKEy8CmNp4NDcCGHC0DayKjhYL4M0dQeidhmu 8lFCZ+jjUsjz5ftyJLo= X-Received: by 10.80.153.69 with SMTP id l5mr18462893edb.7.1499181534748; Tue, 04 Jul 2017 08:18:54 -0700 (PDT) Received: from phenom.ffwll.local ([2a02:168:5640:0:960b:2678:e223:c1c6]) by smtp.gmail.com with ESMTPSA id 2sm23676308edt.36.2017.07.04.08.18.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Jul 2017 08:18:53 -0700 (PDT) From: Daniel Vetter To: DRI Development Subject: [PATCH 10/13] drm/fb-helper: Support deferred setup Date: Tue, 4 Jul 2017 17:18:30 +0200 Message-Id: <20170704151833.17304-11-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20170704151833.17304-1-daniel.vetter@ffwll.ch> References: <20170704151833.17304-1-daniel.vetter@ffwll.ch> Cc: Daniel Vetter , Intel Graphics Development , Thierry Reding X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP FB helper code falls back to a 1024x768 mode if no outputs are connected or don't report back any modes upon initialization. This can be annoying because outputs that are added to FB helper later on can't be used with FB helper if they don't support a matching mode. The fallback is in place because VGA connectors can happen to report an unknown connection status even when they are in fact connected. Some drivers have custom solutions in place to defer FB helper setup until at least one output is connected. But the logic behind these solutions is always the same and there is nothing driver-specific about it, so a better alterative is to fix the FB helper core and add support for all drivers automatically. This patch adds support for deferred FB helper setup. It checks all the connectors for their connection status, and if all of them report to be disconnected marks the FB helper as needing deferred setup. Whet setup is deferred, the FB helper core will automatically retry setup after a hotplug event, and it will keep trying until it succeeds. v2: Rebase onto my entirely reworked fbdev helper locking. One big difference is that this version again drops&reacquires the fbdev lock (which is now fb_helper->lock, but before this patch series it was mode_config->mutex), because register_framebuffer must be able to recurse back into fbdev helper code for the initial screen setup. v3: __drm_fb_helper_initial_config must hold fb_helper->lock upon return, I've fumbled that in the deferred setup case (Liviu). v4: I was blind, redo this all. __drm_fb_helper_initial_config shouldn't need to reacquire fb_helper->lock, that just confuses callers. I myself got confused by kernel_fb_helper_lock and somehow thought it's the same as fb_helper->lock. Tsk. Also simplify the logic a bit (we don't need two functions to probe connectors), we can stick much closer to the existing code. And update some comments I've spotted that are outdated. v5: Don't pass -EAGAIN to drivers, it's just an internal error code (Liviu). v6: Add _and_unlock suffix to clarify locking (Maarten) Cc: Liviu Dudau Cc: John Stultz Cc: Thierry Reding Cc: Maarten Lankhorst Tested-by: John Stultz Signed-off-by: Thierry Reding (v1) Signed-off-by: Daniel Vetter Reviewed-by: Liviu Dudau Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/drm_fb_helper.c | 102 ++++++++++++++++++++++++++-------------- include/drm/drm_fb_helper.h | 23 +++++++++ 2 files changed, 90 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index a35a2ab8e630..135367548027 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -532,6 +532,9 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) if (!drm_fbdev_emulation) return -ENODEV; + if (READ_ONCE(fb_helper->deferred_setup)) + return 0; + mutex_lock(&fb_helper->lock); ret = restore_fbdev_mode(fb_helper); @@ -1616,8 +1619,7 @@ EXPORT_SYMBOL(drm_fb_helper_pan_display); /* * Allocates the backing storage and sets up the fbdev info structure through - * the ->fb_probe callback and then registers the fbdev and sets up the panic - * notifier. + * the ->fb_probe callback. */ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int preferred_bpp) @@ -1715,13 +1717,8 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, } if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { - /* - * hmm everyone went away - assume VGA cable just fell out - * and will come back later. - */ - DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n"); - sizes.fb_width = sizes.surface_width = 1024; - sizes.fb_height = sizes.surface_height = 768; + DRM_INFO("Cannot find any crtc or sizes\n"); + return -EAGAIN; } /* Handle our overallocation */ @@ -2350,6 +2347,59 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, kfree(enabled); } +/* Note: Drops fb_helper->lock before returning. */ +static int +__drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper, + int bpp_sel) +{ + struct drm_device *dev = fb_helper->dev; + struct fb_info *info; + unsigned int width, height; + int ret; + + width = dev->mode_config.max_width; + height = dev->mode_config.max_height; + + drm_setup_crtcs(fb_helper, width, height); + ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); + if (ret < 0) { + if (ret == -EAGAIN) { + fb_helper->preferred_bpp = bpp_sel; + fb_helper->deferred_setup = true; + ret = 0; + } + mutex_unlock(&fb_helper->lock); + + return ret; + } + + fb_helper->deferred_setup = false; + + info = fb_helper->fbdev; + info->var.pixclock = 0; + + /* Need to drop locks to avoid recursive deadlock in + * register_framebuffer. This is ok because the only thing left to do is + * register the fbdev emulation instance in kernel_fb_helper_list. */ + mutex_unlock(&fb_helper->lock); + + ret = register_framebuffer(info); + if (ret < 0) + return ret; + + dev_info(dev->dev, "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + + mutex_lock(&kernel_fb_helper_lock); + if (list_empty(&kernel_fb_helper_list)) + register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); + + list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); + mutex_unlock(&kernel_fb_helper_lock); + + return 0; +} + /** * drm_fb_helper_initial_config - setup a sane initial connector configuration * @fb_helper: fb_helper device struct @@ -2394,39 +2444,15 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, */ int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) { - struct drm_device *dev = fb_helper->dev; - struct fb_info *info; int ret; if (!drm_fbdev_emulation) return 0; mutex_lock(&fb_helper->lock); - drm_setup_crtcs(fb_helper, - dev->mode_config.max_width, - dev->mode_config.max_height); - ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); - mutex_unlock(&fb_helper->lock); - if (ret) - return ret; + ret = __drm_fb_helper_initial_config_and_unlock(fb_helper, bpp_sel); - info = fb_helper->fbdev; - info->var.pixclock = 0; - ret = register_framebuffer(info); - if (ret < 0) - return ret; - - dev_info(dev->dev, "fb%d: %s frame buffer device\n", - info->node, info->fix.id); - - mutex_lock(&kernel_fb_helper_lock); - if (list_empty(&kernel_fb_helper_list)) - register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); - - list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); - mutex_unlock(&kernel_fb_helper_lock); - - return 0; + return ret; } EXPORT_SYMBOL(drm_fb_helper_initial_config); @@ -2459,6 +2485,12 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&fb_helper->lock); + if (fb_helper->deferred_setup) { + err = __drm_fb_helper_initial_config_and_unlock(fb_helper, + fb_helper->preferred_bpp); + return err; + } + if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) { fb_helper->delayed_hotplug = true; mutex_unlock(&fb_helper->lock); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index ea170b96e88d..a5ea6ffdfecc 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -232,6 +232,29 @@ struct drm_fb_helper { * needs to be reprobe when fbdev is in control again. */ bool delayed_hotplug; + + /** + * @deferred_setup: + * + * If no outputs are connected (disconnected or unknown) the FB helper + * code will defer setup until at least one of the outputs shows up. + * This field keeps track of the status so that setup can be retried + * at every hotplug event until it succeeds eventually. + * + * Protected by @lock. + */ + bool deferred_setup; + + /** + * @preferred_bpp: + * + * Temporary storage for the driver's preferred BPP setting passed to + * FB helper initialization. This needs to be tracked so that deferred + * FB helper setup can pass this on. + * + * See also: @deferred_setup + */ + int preferred_bpp; }; /**