From patchwork Thu Dec 20 00:19:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lyude Paul X-Patchwork-Id: 10738375 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 E74481399 for ; Thu, 20 Dec 2018 00:24:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D69EC2852D for ; Thu, 20 Dec 2018 00:24:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CA712287BD; Thu, 20 Dec 2018 00:24:50 +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=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 69A0C2852D for ; Thu, 20 Dec 2018 00:24:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A10DD6F235; Thu, 20 Dec 2018 00:24:23 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTPS id 53D1D6F229; Thu, 20 Dec 2018 00:24:15 +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 C421DD81; Thu, 20 Dec 2018 00:24:14 +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 C8AA910018F8; Thu, 20 Dec 2018 00:24:13 +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 Subject: [PATCH v2 05/16] drm/dp_mst: Fix payload deallocation on hotplugs using malloc refs Date: Wed, 19 Dec 2018 19:19:49 -0500 Message-Id: <20181220001959.12486-6-lyude@redhat.com> In-Reply-To: <20181220001959.12486-1-lyude@redhat.com> References: <20181220001959.12486-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.28]); Thu, 20 Dec 2018 00:24:14 +0000 (UTC) X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: David Airlie , Jerry Zuo , Juston Li Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Up until now, freeing payloads on remote MST hubs that just had ports removed has almost never worked because we've been relying on port validation in order to stop us from accessing ports that have already been freed from memory, but ports which need their payloads released due to being removed will never be a valid part of the topology after they've been removed. Since we've introduced malloc refs, we can replace all of the validation logic in payload helpers which are used for deallocation with some well-placed malloc krefs. This ensures that regardless of whether or not the ports are still valid and in the topology, any port which has an allocated payload will remain allocated in memory until it's payloads have been removed - finally allowing us to actually release said payloads correctly. Signed-off-by: Lyude Paul Reviewed-by: Daniel Vetter Cc: David Airlie Cc: Jerry Zuo Cc: Harry Wentland Cc: Juston Li Reviewed-by: Harry Wentland --- drivers/gpu/drm/drm_dp_mst_topology.c | 54 +++++++++++++++------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index ef8637f37564..11dd3ede7b7d 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2100,10 +2100,6 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, u8 sinks[DRM_DP_MAX_SDP_STREAMS]; int i; - port = drm_dp_mst_topology_get_port_validated(mgr, port); - if (!port) - return -EINVAL; - port_num = port->port_num; mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent); if (!mstb) { @@ -2111,10 +2107,8 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, port->parent, &port_num); - if (!mstb) { - drm_dp_mst_topology_put_port(port); + if (!mstb) return -EINVAL; - } } txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); @@ -2151,7 +2145,6 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, kfree(txmsg); fail_put: drm_dp_mst_topology_put_mstb(mstb); - drm_dp_mst_topology_put_port(port); return ret; } @@ -2256,15 +2249,16 @@ static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr, */ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) { - int i, j; - int cur_slots = 1; struct drm_dp_payload req_payload; struct drm_dp_mst_port *port; + int i, j; + int cur_slots = 1; mutex_lock(&mgr->payload_lock); for (i = 0; i < mgr->max_payloads; i++) { struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i]; struct drm_dp_payload *payload = &mgr->payloads[i]; + bool put_port = false; /* solve the current payloads - compare to the hw ones - update the hw view */ @@ -2272,12 +2266,20 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) if (vcpi) { port = container_of(vcpi, struct drm_dp_mst_port, vcpi); - port = drm_dp_mst_topology_get_port_validated(mgr, - port); - if (!port) { - mutex_unlock(&mgr->payload_lock); - return -EINVAL; + + /* Validated ports don't matter if we're releasing + * VCPI + */ + if (vcpi->num_slots) { + port = drm_dp_mst_topology_get_port_validated( + mgr, port); + if (!port) { + mutex_unlock(&mgr->payload_lock); + return -EINVAL; + } + put_port = true; } + req_payload.num_slots = vcpi->num_slots; req_payload.vcpi = vcpi->vcpi; } else { @@ -2309,7 +2311,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) } cur_slots += req_payload.num_slots; - if (port) + if (put_port) drm_dp_mst_topology_put_port(port); } @@ -3124,6 +3126,8 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n", pbn, port->vcpi.num_slots); + /* Keep port allocated until it's payload has been removed */ + drm_dp_mst_get_port_malloc(port); drm_dp_mst_topology_put_port(port); return true; out: @@ -3153,11 +3157,12 @@ EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots); */ void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) { - port = drm_dp_mst_topology_get_port_validated(mgr, port); - if (!port) - return; + /* + * A port with VCPI will remain allocated until it's VCPI is + * released, no verified ref needed + */ + port->vcpi.num_slots = 0; - drm_dp_mst_topology_put_port(port); } EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); @@ -3169,16 +3174,17 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) { - port = drm_dp_mst_topology_get_port_validated(mgr, port); - if (!port) - return; + /* + * A port with VCPI will remain allocated until it's VCPI is + * released, no verified ref needed + */ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); port->vcpi.num_slots = 0; port->vcpi.pbn = 0; port->vcpi.aligned_pbn = 0; port->vcpi.vcpi = 0; - drm_dp_mst_topology_put_port(port); + drm_dp_mst_put_port_malloc(port); } EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi);