Received: by 2002:ac0:aa62:0:0:0:0:0 with SMTP id w31-v6csp76223ima; Tue, 23 Oct 2018 19:52:25 -0700 (PDT) X-Google-Smtp-Source: AJdET5fhyNzyI0hh3WlbpmkqFn82n4VheO6zpB3R2iiIVkwajGCDESRSkiNZ3FkrPnhou/LYuk1B X-Received: by 2002:a17:902:a58c:: with SMTP id az12-v6mr803262plb.266.1540349544932; Tue, 23 Oct 2018 19:52:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1540349544; cv=none; d=google.com; s=arc-20160816; b=FBoyeA/veLos1MI8Z7ZYDAOQtQ6VkJxKLhyJnKkZmA0nsX2g1+Jc339nbosC6AiFUv yMPOTsa4OrZYn+IsqXaD3ptiwcxsUL3iJ067Dpezny2B+cED6oCQRZn+u7Db7OaMhTAJ WvN3CyKg6aj+G/0yScKINC5PJ5b24ZxHBHIaoULbJSPi6thGCZsLAWJFJg4qBnWQZM1N aHaf5FjBYP+aM7bH9nRJeU+1cYOB97NFihAXprKiyUESDb0bzKcXzHkVAP/bQ2nQlhR3 NhLcDFrfS8wsO3KGbTe83ib0mvMsACEqwLVGp+z72Yy6oNGHPsKs4SpcnGfDI8JrYLjs JNog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=qgmoqvyQMddm8dtCaePOVdNIPxQrY/o86ZyiEvN2sSw=; b=XmR3+uRZhWrPCrckQVbI1JZnqC91FkrqeHnXbIZe2cVRrzK/GjEUbBYtPcV+3VYWHf ir13bF4gNUZd/zx5bKA25OBCwR1H43cVAA7WRNtbiYEB0rsjXXb13GvdCPdVacmpj9cL NmKwSq6viQw1UbYAZwmhr1S3yoPVn4GlmRsb2DspS0f2GkhhNPzIlPm5mxFgNEh0ZFD4 D7iMA8hgBHdrnLFGYawkAYqjv03tWGykvweYPguUN8NjrWJxClgVhg+hwG6ZKlAWk1Om g2Nd61TPDdgWdcAu8lqs05yH25o4eGw9LWHvs8OOJYJZmo8vNXf4GqfFimWmjDz4w1px 1SAQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g7-v6si3226305pgj.116.2018.10.23.19.52.09; Tue, 23 Oct 2018 19:52:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726919AbeJXLPl (ORCPT + 99 others); Wed, 24 Oct 2018 07:15:41 -0400 Received: from mga11.intel.com ([192.55.52.93]:41763 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725826AbeJXLPl (ORCPT ); Wed, 24 Oct 2018 07:15:41 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 23 Oct 2018 19:22:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,418,1534834800"; d="scan'208";a="102098586" Received: from jhli-desk1.jf.intel.com ([10.7.198.167]) by orsmga001.jf.intel.com with ESMTP; 23 Oct 2018 19:22:28 -0700 From: Juston Li To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: lyude@redhat.com, clinton.a.taylor@intel.com, nathan.d.ciobanu@intel.com, mario.limonciello@dell.com, jared_dominguez@dell.com, linux-kernel@vger.kernel.org, Lyude , stable@vger.kernel.org, Juston Li Subject: [RESEND PATCH v2 1/2] drm/dp/mst: Reprobe EDID for MST ports on resume Date: Tue, 23 Oct 2018 19:19:24 -0700 Message-Id: <20181024021925.27026-2-juston.li@intel.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181024021925.27026-1-juston.li@intel.com> References: <20181024021925.27026-1-juston.li@intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Lyude As observed with the latest ThinkPad docks, we unfortunately can't rely on docks keeping us updated with hotplug events that happened while we were suspended. On top of that, even if the number of connectors remains the same between suspend and resume it's still not safe to assume that there were no hotplugs, since a different monitor might have been plugged into a port another monitor previously occupied. As such, we need to go through all of the MST ports and check whether or not their EDIDs have changed. In addition to that, we also now return -EINVAL from drm_dp_mst_topology_mgr_resume to indicate to callers that they need to reset the MST connection, and that they can't rely on any other method of reprobing. Cc: stable@vger.kernel.org Signed-off-by: Lyude Signed-off-by: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 94 ++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 5ff1d79b86c4..88abebe52021 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -2201,6 +2202,64 @@ void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr) } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend); +static bool drm_dp_mst_edids_changed(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port) +{ + struct drm_device *dev; + struct drm_connector *connector; + struct drm_dp_mst_port *dport; + struct drm_dp_mst_branch *mstb; + struct edid *current_edid, *cached_edid; + bool ret = false; + + port = drm_dp_get_validated_port_ref(mgr, port); + if (!port) + return false; + + mstb = drm_dp_get_validated_mstb_ref(mgr, port->mstb); + if (mstb) { + list_for_each_entry(dport, &port->mstb->ports, next) { + ret = drm_dp_mst_edids_changed(mgr, dport); + if (ret) + break; + } + + drm_dp_put_mst_branch_device(mstb); + if (ret) + goto out; + } + + connector = port->connector; + if (!connector || !port->aux.ddc.algo) + goto out; + + dev = connector->dev; + mutex_lock(&dev->mode_config.mutex); + + current_edid = drm_get_edid(connector, &port->aux.ddc); + if (connector->edid_blob_ptr) + cached_edid = (void *)connector->edid_blob_ptr->data; + else + return false; + + if ((current_edid && cached_edid && memcmp(current_edid, cached_edid, + sizeof(struct edid)) != 0) || + (!current_edid && cached_edid) || (current_edid && !cached_edid)) { + ret = true; + DRM_DEBUG_KMS("EDID on %s changed, reprobing connectors\n", + connector->name); + } + + mutex_unlock(&dev->mode_config.mutex); + + kfree(current_edid); + +out: + drm_dp_put_port(port); + + return ret; +} + /** * drm_dp_mst_topology_mgr_resume() - resume the MST manager * @mgr: manager to resume @@ -2210,9 +2269,15 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend); * * if the device fails this returns -1, and the driver should do * a full MST reprobe, in case we were undocked. + * + * if the device can no longer be trusted, this returns -EINVAL + * and the driver should unconditionally disconnect and reconnect + * the dock. */ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr) { + struct drm_dp_mst_branch *mstb; + struct drm_dp_mst_port *port; int ret = 0; mutex_lock(&mgr->lock); @@ -2246,8 +2311,35 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr) drm_dp_check_mstb_guid(mgr->mst_primary, guid); ret = 0; - } else + + /* + * Some hubs also forget to notify us of hotplugs that happened + * while we were in suspend, so we need to verify that the edid + * hasn't changed for any of the connectors. If it has been, + * we unfortunately can't rely on the dock updating us with + * hotplug events, so indicate we need a full reconnect. + */ + + /* MST's I2C helpers can't be used while holding this lock */ + mutex_unlock(&mgr->lock); + + mstb = drm_dp_get_validated_mstb_ref(mgr, mgr->mst_primary); + if (mstb) { + list_for_each_entry(port, &mstb->ports, next) { + if (drm_dp_mst_edids_changed(mgr, port)) { + ret = -EINVAL; + break; + } + } + + drm_dp_put_mst_branch_device(mstb); + } + } else { ret = -1; + mutex_unlock(&mgr->lock); + } + + return ret; out_unlock: mutex_unlock(&mgr->lock); -- 2.17.2