Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1528792imu; Thu, 13 Dec 2018 17:28:19 -0800 (PST) X-Google-Smtp-Source: AFSGD/WJYrvRfyodsboZhPhqP8k03jTQHtXy+1sLMKKtvHBlt0m5F8asCwezPUBD5iJH0tZtJ9Hz X-Received: by 2002:a63:5c22:: with SMTP id q34mr928869pgb.417.1544750899220; Thu, 13 Dec 2018 17:28:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544750899; cv=none; d=google.com; s=arc-20160816; b=VLbITnrv/Jx5u37nsd6ozrPubv4oNASnnnq28jbKfG6xJpRPXJZGUOH6zbB5s3k3Wh s1GWfcJzJLPTjJ1v6SMtuf6UAqfp0Xh4VrWdemfmlbeNIqBVnXCNkGkD1lscC33aEp2N 8F4DpljxrbJb0V3D4WHdrMMPzb5H80SwetsOxe3wpdATc7N6jY3N/jB5sJhInsNgVscR 05jS09aBlzUOpAqwIZYl5+zdXIluksPir/4n5aB/y0T3jDI14dmIztsZFUZo8+mZVtGl ki2wvBu1MWzm9qctfx1TJjpa7DveY+Oumjs3lJdkJ5Ax4Ij2U2yD9ca++lYbjvyYJyEi 8CkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=EzrBVk4hD9mw8YAjvJ3MCdM6rmV3OiBp8CvmkhyQ984=; b=YpwIz1B0koVvG+22AY/aD3snbU5gSXijtSrnHK1dnjw6SB9QMt5kz/H8oZiXDzR8m1 2v6USMg+h52hpJYGY14rGMkuBJ1tPJHk8Z3ypYfve8cYPNEjSwxlTxE9fal28TVS+cyk cCLzEx+UuDZzY5KHehZsswZko7UKCYUvMEnUsB0hZop1bRPgUL2NSwHlytIRZYrS61gi 97rsDBrVZsj7fxDZU50SXSe2pLtNb0ZIu27hrGshFdHlv8wO/1jI8JFn55d9c+epKaml ZnPmw8gDvVPmu8mOZKEsOyb0YvrQnfUNk+QdMEJXTSU6q9fjj4sbduLc1BeUFj89z/1/ Liuw== 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=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f22si2795268pgm.81.2018.12.13.17.28.04; Thu, 13 Dec 2018 17:28:19 -0800 (PST) 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=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729416AbeLNB0p (ORCPT + 99 others); Thu, 13 Dec 2018 20:26:45 -0500 Received: from mx1.redhat.com ([209.132.183.28]:33846 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727901AbeLNB0n (ORCPT ); Thu, 13 Dec 2018 20:26:43 -0500 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 mx1.redhat.com (Postfix) with ESMTPS id E867330841DE; Fri, 14 Dec 2018 01:26:42 +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 8A1C66012B; Fri, 14 Dec 2018 01:26:41 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, amd-gfx@lists.freedesktop.org Cc: Daniel Vetter , Dave Airlie , Harry Wentland , Jerry Zuo , Maarten Lankhorst , Maxime Ripard , Sean Paul , David Airlie , linux-kernel@vger.kernel.org Subject: [WIP PATCH 05/15] drm/dp_mst: Fix payload deallocation on hotplugs using malloc refs Date: Thu, 13 Dec 2018 20:25:34 -0500 Message-Id: <20181214012604.13746-6-lyude@redhat.com> In-Reply-To: <20181214012604.13746-1-lyude@redhat.com> References: <20181214012604.13746-1-lyude@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Fri, 14 Dec 2018 01:26:43 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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 ae9d019af9f2..93f08bfd2ab3 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1989,10 +1989,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) { @@ -2000,10 +1996,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); @@ -2032,7 +2026,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; } @@ -2137,15 +2130,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 */ @@ -2153,12 +2147,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 { @@ -2190,7 +2192,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); } @@ -3005,6 +3007,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: @@ -3034,11 +3038,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); @@ -3050,16 +3055,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); -- 2.19.2