From patchwork Thu Jan 3 00:06:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lyude Paul X-Patchwork-Id: 10746725 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 916161399 for ; Thu, 3 Jan 2019 00:07:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 81A0A28066 for ; Thu, 3 Jan 2019 00:07:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 75F7428396; Thu, 3 Jan 2019 00:07:07 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham 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 0916528066 for ; Thu, 3 Jan 2019 00:07:07 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4EBCC6E8FA; Thu, 3 Jan 2019 00:06:52 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTPS id A82FF6E52C; Thu, 3 Jan 2019 00:06:50 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 29AA92CD7EE; Thu, 3 Jan 2019 00:06:50 +0000 (UTC) Received: from malachite.bss.redhat.com (dhcp-10-20-1-11.bss.redhat.com [10.20.1.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1EEA41001947; Thu, 3 Jan 2019 00:06:49 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, nouveau@lists.freedesktop.org, amd-gfx@lists.freedesktop.org Date: Wed, 2 Jan 2019 19:06:22 -0500 Message-Id: <20190103000635.13628-4-lyude@redhat.com> In-Reply-To: <20190103000635.13628-1-lyude@redhat.com> References: <20190103000635.13628-1-lyude@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 03 Jan 2019 00:06:50 +0000 (UTC) Subject: [Intel-gfx] [PATCH v3 03/16] drm/dp_mst: Restart last_connected_port_and_mstb() if topology ref fails X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jerry Zuo , David Airlie , Harry Wentland Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP While this isn't a complete fix, this will improve the reliability of drm_dp_get_last_connected_port_and_mstb() pretty significantly during hotplug events, since there's a chance that the in-memory topology tree may not be fully updated when drm_dp_get_last_connected_port_and_mstb() is called and thus might end up causing our search to fail on an mstb whose topology refcount has reached 0, but has not yet been removed from it's parent. Ideally, we should further fix this problem by ensuring that we deal with the potential for racing with a hotplug event, which would look like this: * drm_dp_payload_send_msg() retrieves the last living relative of mstb with drm_dp_get_last_connected_port_and_mstb() * drm_dp_payload_send_msg() starts building payload message At the same time, mstb gets unplugged from the topology and is no longer the actual last living relative of the original mstb * drm_dp_payload_send_msg() tries sending the payload message, hub times out * Hub timed out, we give up and run away-resulting in the payload being leaked This could be fixed by restarting the drm_dp_get_last_connected_port_and_mstb() search whenever we get a timeout, sending the payload to the new mstb, then repeating until either the entire topology is removed from the system or drm_dp_get_last_connected_port_and_mstb() fails. But since the above race condition is not terribly likely, we'll address that in a later patch series once we've improved the recovery handling for VCPI allocations in the rest of the DP MST helpers. Signed-off-by: Lyude Paul Cc: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li --- drivers/gpu/drm/drm_dp_mst_topology.c | 54 ++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index c0dc20fbd55a..b8a47c795fa9 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2045,24 +2045,50 @@ static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent); } -static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_branch *mstb, - int *port_num) +/** + * drm_dp_get_last_connected_port_and_mstb() - Find the last living relatives + * in a topology of a given branch device + * @mgr: The topology manager to use + * @mstb: The disconnected branch device + * @port_num: Where to store the number of the last connected port + * + * Searches upwards in the topology starting from @mstb to try to find the + * closest available parent of @mstb that's still connected to the rest of the + * topology. This can be used in order to perform operations like releasing + * payloads, where the branch device which owned the payload may no longer be + * around and thus would require that the payload on the last living relative + * be freed instead. + * + * Returns: + * The last connected &drm_dp_mst_branch in the topology that was a parent of + * @mstb, if there is one. + */ +static struct drm_dp_mst_branch * +drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_branch *mstb, + int *port_num) { struct drm_dp_mst_branch *rmstb = NULL; struct drm_dp_mst_port *found_port; + mutex_lock(&mgr->lock); - if (mgr->mst_primary) { + if (!mgr->mst_primary) + goto out; + + do { found_port = drm_dp_get_last_connected_port_to_mstb(mstb); + if (!found_port) + break; - if (found_port) { + if (drm_dp_mst_topology_try_get_mstb(found_port->parent)) { rmstb = found_port->parent; - if (drm_dp_mst_topology_try_get_mstb(rmstb)) - *port_num = found_port->port_num; - else - rmstb = NULL; + *port_num = found_port->port_num; + } else { + /* Search again, starting from this parent */ + mstb = found_port->parent; } - } + } while (!rmstb); +out: mutex_unlock(&mgr->lock); return rmstb; } @@ -2111,6 +2137,14 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, drm_dp_queue_down_tx(mgr, txmsg); + /* + * FIXME: there is a small chance that between getting the last + * connected mstb and sending the payload message, the last connected + * mstb could also be removed from the topology. In the future, this + * needs to be fixed by restarting the + * drm_dp_get_last_connected_port_and_mstb() search in the event of a + * timeout if the topology is still connected to the system. + */ ret = drm_dp_mst_wait_tx_reply(mstb, txmsg); if (ret > 0) { if (txmsg->reply.reply_type == 1) {