From patchwork Tue May 26 18:23:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lyude Paul X-Patchwork-Id: 11571027 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 35B5792A for ; Tue, 26 May 2020 18:23:33 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 132AF20870 for ; Tue, 26 May 2020 18:23:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="VN686CrK" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 132AF20870 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EAC926E255; Tue, 26 May 2020 18:23:26 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 49D396E03B for ; Tue, 26 May 2020 18:23:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1590517403; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7OjjA8amLYnyqilHHxB8H6n6KWHY9pD00xJgS/xdmTI=; b=VN686CrKO7LhGyQ5TaOhLJt9zvlSdgJlYNZljiyRCQmhWTVj7JwMqI9QrzDKwKmVWQ5+aR 9OzIH+Kla3KkHmKhaZjndeVxz/HIeP3txyTEUIAjb0iNTsd7Mm0KWheI2BG+Dh0RIK0AGk pEr3pmKGOG+4fb83sSJX3X+VGe+5Rsw= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-222-qmoxgcvCPeW5OUIFwfxxWw-1; Tue, 26 May 2020 14:23:22 -0400 X-MC-Unique: qmoxgcvCPeW5OUIFwfxxWw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5836B1005510; Tue, 26 May 2020 18:23:20 +0000 (UTC) Received: from Whitewolf.redhat.com (ovpn-120-19.rdu2.redhat.com [10.10.120.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id D847D78B2D; Tue, 26 May 2020 18:23:17 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org Subject: [PATCH 1/2] drm/probe_helper: Add drm_connector_helper_funcs.mode_valid_ctx Date: Tue, 26 May 2020 14:23:09 -0400 Message-Id: <20200526182313.4005-2-lyude@redhat.com> In-Reply-To: <20200526182313.4005-1-lyude@redhat.com> References: <20200526182313.4005-1-lyude@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: David Airlie , linux-kernel@vger.kernel.org, Thomas Zimmermann , Lee Shawn C Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" This is just an atomic version of mode_valid, which is intended to be used for situations where a driver might need to check the atomic state of objects other than the connector itself. One such example is with MST, where the maximum possible bandwidth on a connector can change dynamically irregardless of the display configuration. Signed-off-by: Lyude Paul Cc: Lee Shawn C Tested-by: Lee Shawn C Reviewed-by: Imre Deak --- drivers/gpu/drm/drm_crtc_helper_internal.h | 6 +- drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++-------- include/drm/drm_modeset_helper_vtables.h | 41 ++++++++++++++ 3 files changed, 88 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h b/drivers/gpu/drm/drm_crtc_helper_internal.h index f0a66ef47e5ad..ca767cba6094d 100644 --- a/drivers/gpu/drm/drm_crtc_helper_internal.h +++ b/drivers/gpu/drm/drm_crtc_helper_internal.h @@ -73,8 +73,10 @@ enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode); enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode); -enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode); +enum drm_mode_status +drm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx); struct drm_encoder * drm_connector_get_single_encoder(struct drm_connector *connector); diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 466dfbba82564..3132784736841 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -86,16 +86,17 @@ drm_mode_validate_flag(const struct drm_display_mode *mode, return MODE_OK; } -static enum drm_mode_status +static int drm_mode_validate_pipeline(struct drm_display_mode *mode, - struct drm_connector *connector) + struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx) { struct drm_device *dev = connector->dev; - enum drm_mode_status ret = MODE_OK; struct drm_encoder *encoder; + int ret = MODE_OK; /* Step 1: Validate against connector */ - ret = drm_connector_mode_valid(connector, mode); + ret = drm_connector_mode_valid(connector, mode, ctx); if (ret != MODE_OK) return ret; @@ -196,16 +197,23 @@ enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder, return encoder_funcs->mode_valid(encoder, mode); } -enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +int +drm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx) { const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; - if (!connector_funcs || !connector_funcs->mode_valid) + if (!connector_funcs) return MODE_OK; - return connector_funcs->mode_valid(connector, mode); + if (connector_funcs->mode_valid_ctx) + return connector_funcs->mode_valid_ctx(connector, mode, ctx); + else if (connector_funcs->mode_valid) + return connector_funcs->mode_valid(connector, mode); + else + return MODE_OK; } #define DRM_OUTPUT_POLL_PERIOD (10*HZ) @@ -375,8 +383,9 @@ EXPORT_SYMBOL(drm_helper_probe_detect); * (if specified) * - drm_mode_validate_flag() checks the modes against basic connector * capabilities (interlace_allowed,doublescan_allowed,stereo_allowed) - * - the optional &drm_connector_helper_funcs.mode_valid helper can perform - * driver and/or sink specific checks + * - the optional &drm_connector_helper_funcs.mode_valid or + * &drm_connector_helper_funcs.mode_valid_ctx helpers can perform driver + * and/or sink specific checks * - the optional &drm_crtc_helper_funcs.mode_valid, * &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid * helpers can perform driver and/or source specific checks which are also @@ -507,22 +516,34 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, mode_flags |= DRM_MODE_FLAG_3D_MASK; list_for_each_entry(mode, &connector->modes, head) { - if (mode->status == MODE_OK) - mode->status = drm_mode_validate_driver(dev, mode); + if (mode->status != MODE_OK) + continue; + + mode->status = drm_mode_validate_driver(dev, mode); + if (mode->status != MODE_OK) + continue; - if (mode->status == MODE_OK) - mode->status = drm_mode_validate_size(mode, maxX, maxY); + mode->status = drm_mode_validate_size(mode, maxX, maxY); + if (mode->status != MODE_OK) + continue; - if (mode->status == MODE_OK) - mode->status = drm_mode_validate_flag(mode, mode_flags); + mode->status = drm_mode_validate_flag(mode, mode_flags); + if (mode->status != MODE_OK) + continue; - if (mode->status == MODE_OK) - mode->status = drm_mode_validate_pipeline(mode, - connector); + ret = drm_mode_validate_pipeline(mode, connector, &ctx); + if (ret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry; + } else if (WARN_ON_ONCE(ret < 0)) { + mode->status = MODE_BAD; + } else { + mode->status = ret; + } - if (mode->status == MODE_OK) - mode->status = drm_mode_validate_ycbcr420(mode, - connector); + if (mode->status != MODE_OK) + continue; + mode->status = drm_mode_validate_ycbcr420(mode, connector); } prune: diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 421a30f084631..8f020c3424b2b 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -968,6 +968,47 @@ struct drm_connector_helper_funcs { */ enum drm_mode_status (*mode_valid)(struct drm_connector *connector, struct drm_display_mode *mode); + + /** + * @mode_valid_ctx: + * + * Callback to validate a mode for a connector, irrespective of the + * specific display configuration. + * + * This callback is used by the probe helpers to filter the mode list + * (which is usually derived from the EDID data block from the sink). + * See e.g. drm_helper_probe_single_connector_modes(). + * + * This function is optional, and is the atomic version of + * &drm_connector_funcs.mode_valid. + * + * To allow for accessing the atomic state of modesetting objects, the + * helper libraries always call this with ctx set to a valid context, + * and &drm_mode_config.connection_mutex will always be locked with + * the ctx parameter set to @ctx. This allows for taking additional + * locks as required. + * + * Even though additional locks may be acquired, this callback is + * still expected not to take any constraints into account which would + * be influenced by the currently set display state - such constraints + * should be handled in the driver's atomic check. For example, if a + * connector shares display bandwidth with other connectors then it + * would be ok to validate a mode uses against the maximum possible + * bandwidth of the connector. But it wouldn't be ok to take the + * current bandwidth usage of other connectors into account, as this + * would change depending on the display state. + * + * Returns: + * + * Either &drm_mode_status.MODE_OK, one of the failure reasons in + * &enum drm_mode_status, or -EDEADLK if a deadlock would have + * occurred and we need to backoff. + * + */ + int (*mode_valid_ctx)(struct drm_connector *connector, + struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx); + /** * @best_encoder: * From patchwork Tue May 26 18:23:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lyude Paul X-Patchwork-Id: 11571031 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 10E23913 for ; Tue, 26 May 2020 18:23:37 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id E3E1120776 for ; Tue, 26 May 2020 18:23:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="SJGhvC7X" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E3E1120776 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 323486E25C; Tue, 26 May 2020 18:23:35 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by gabe.freedesktop.org (Postfix) with ESMTPS id ECD316E25A for ; Tue, 26 May 2020 18:23:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1590517409; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qkybwaL5hV3//CnMmHVpyyCIBF14CepvpJObWY76xLg=; b=SJGhvC7Xy43yFhtH9olVtQM5a6zpufe7WzBRwlykORyUAEGuVgf3yqbOUIN71fkncFjPLX 65+9V0NccwNKq7eNnQTtJ9r2wFs52o1OkU9DIKb+RQnV6aQVHJMIxWzirSw7Odlgn8fR/n usaoo4tdf41cF2U871JGWZfAElujxys= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-237-yT4UDOvfM4Kj0e1axdhmBw-1; Tue, 26 May 2020 14:23:25 -0400 X-MC-Unique: yT4UDOvfM4Kj0e1axdhmBw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7C56E1005510; Tue, 26 May 2020 18:23:23 +0000 (UTC) Received: from Whitewolf.redhat.com (ovpn-120-19.rdu2.redhat.com [10.10.120.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id DA34778B2D; Tue, 26 May 2020 18:23:21 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org Subject: [PATCH 2/2] drm/i915/mst: filter out the display mode exceed sink's capability Date: Tue, 26 May 2020 14:23:10 -0400 Message-Id: <20200526182313.4005-3-lyude@redhat.com> In-Reply-To: <20200526182313.4005-1-lyude@redhat.com> References: <20200526182313.4005-1-lyude@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Cooper Chiou , David Airlie , intel-gfx@lists.freedesktop.org, Lucas De Marchi , linux-kernel@vger.kernel.org, Manasi Navare , =?utf-8?q?Jos=C3=A9_Roberto_de_Souza?= , Rodrigo Vivi , Lee Shawn C Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Lee Shawn C So far, max dot clock rate for MST mode rely on physcial bandwidth limitation. It would caused compatibility issue if source display resolution exceed MST hub output ability. For example, source DUT had DP 1.2 output capability. And MST docking just support HDMI 1.4 spec. When a HDMI 2.0 monitor connected. Source would retrieve EDID from external and get max resolution 4k@60fps. DP 1.2 can support 4K@60fps because it did not surpass DP physical bandwidth limitation. Do modeset to 4k@60fps, source output display data but MST docking can't output HDMI properly due to this resolution already over HDMI 1.4 spec. Refer to commit ("drm/dp_mst: Use full_pbn instead of available_pbn for bandwidth checks"). Source driver should refer to full_pbn to evaluate sink output capability. And filter out the resolution surpass sink output limitation. v2: Using mgr->base.lock to protect full_pbn. v3: Add ctx lock. v4: * s/intel_dp_mst_mode_clock_exceed_pbn_bandwidth/ intel_dp_mst_mode_clock_exceeds_pbn_bw/ * Use the new drm_connector_helper_funcs.mode_valid_ctx to properly pipe down the drm_modeset_acquire_ctx that the probe helpers are using, so we can safely grab &mgr->base.lock without deadlocking Cc: Manasi Navare Cc: Jani Nikula Cc: Ville Syrjala Cc: Cooper Chiou Co-developed-by: Lyude Paul Signed-off-by: Lee Shawn C Tested-by: Lee Shawn C Signed-off-by: Lyude Paul --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 39 ++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index d18b406f2a7d2..cf052095ad785 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -610,15 +610,42 @@ static int intel_dp_mst_get_modes(struct drm_connector *connector) return intel_dp_mst_get_ddc_modes(connector); } +static int +intel_dp_mst_mode_clock_exceeds_pbn_bw(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + int clock, int bpp) +{ + struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_dp *intel_dp = intel_connector->mst_port; + struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr; + struct drm_dp_mst_port *port = (to_intel_connector(connector))->port; + int ret = MODE_OK; + + if (!mgr) + return ret; + + ret = drm_modeset_lock(&mgr->base.lock, ctx); + if (ret == -EDEADLK) + return ret; + + if (port->full_pbn && + drm_dp_calc_pbn_mode(clock, bpp, false) > port->full_pbn) + ret = MODE_CLOCK_HIGH; + + return ret; +} + static enum drm_mode_status -intel_dp_mst_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, + struct drm_display_mode *mode, + struct drm_modeset_acquire_ctx *ctx) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dp *intel_dp = intel_connector->mst_port; int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; + int ret; if (drm_connector_is_unregistered(connector)) return MODE_ERROR; @@ -632,7 +659,11 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); mode_rate = intel_dp_link_required(mode->clock, 18); - /* TODO - validate mode against available PBN for link */ + ret = intel_dp_mst_mode_clock_exceeds_pbn_bw(connector, ctx, + mode->clock, 24); + if (ret != MODE_OK) + return ret; + if (mode->clock < 10000) return MODE_CLOCK_LOW; @@ -671,7 +702,7 @@ intel_dp_mst_detect(struct drm_connector *connector, static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = { .get_modes = intel_dp_mst_get_modes, - .mode_valid = intel_dp_mst_mode_valid, + .mode_valid_ctx = intel_dp_mst_mode_valid_ctx, .atomic_best_encoder = intel_mst_atomic_best_encoder, .atomic_check = intel_dp_mst_atomic_check, .detect_ctx = intel_dp_mst_detect,