From patchwork Fri Aug 4 18:23:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131342 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp84779vqr; Fri, 4 Aug 2023 13:31:04 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGrPAiJ8xoL1QhTXWaZPpnQ2WFniWeRVQc0j7bVoFp68invA+0b6C9X1EBswCU5KFr4F6Np X-Received: by 2002:a17:906:208:b0:99b:ea8f:9003 with SMTP id 8-20020a170906020800b0099bea8f9003mr2579377ejd.50.1691181064674; Fri, 04 Aug 2023 13:31:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691181064; cv=none; d=google.com; s=arc-20160816; b=YN0sohkSSavXpeeb1ibV8b8am6lsHgLduB6c7hAvkLAoIFSY9ButTbv6XXNz/Yeqaa oc5Y0CbPdDCM1bU4P3Fxd5bzXpopJuNFVj8HqHE54NJr3Hwb0tjklMijk60DZFxkT9Jl qu/aYrZ9+CyqjOC647w9pOLKmZW0d5VLLLCNDq0C5tNiNl954vWItDJe0WujP2eIhfln HE0+vr9iDcOIdLoyvsN+3IG+DRx5ASwvatUdcHtD36dhusy2G7ZgvWq/OLKKRqHArEMJ C/qUhz7/xDfQ1HZodr9W9o6quA1gcAGwg31diniV53Ew1rVIcnjHOQkhG1rUry6TGJpd fDwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=NfuUlvOtQCcgIWDDGRTDaO97w4Wpv+IQfrkVs47IV0U=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=FAKV3lUGcj3Q5TXWVHvl/KXYOt5lb5lq3Pfs6NBOMSy/9uYdOhNxq9T33Vlv9NESDP NMDoVOT+8aYBvSen77tb6/qnSMHhlD6aWKyGxcFHThP8nSl4UDJsIOxnP75OEbCil7a9 KSJ9nfS9DK9S1X9/2wR/RNcR4UD+g34wQ+GE/LLjtOdxflH9A7gxvnm3B4RiSHUokFie 55oYsMcTsFqCv5lWUmBpFXrDD5OoJ7PIzTZhOpkmpNvT7OxlctEkpThXDe9Q4QCzNNJO k173D38kpWXxrEUV00qwnS0vYdHUzrbzBuyFJ5NeLmngpv0AvmUx3qDvjOaFSNtHnIgh BbEg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=LGn0YbsK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n21-20020a17090625d500b0098e417a0c3bsi2083436ejb.109.2023.08.04.13.30.11; Fri, 04 Aug 2023 13:31:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=LGn0YbsK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231220AbjHDSZj (ORCPT + 99 others); Fri, 4 Aug 2023 14:25:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52976 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231296AbjHDSZK (ORCPT ); Fri, 4 Aug 2023 14:25:10 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CB00046B2 for ; Fri, 4 Aug 2023 11:24:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173459; 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=NfuUlvOtQCcgIWDDGRTDaO97w4Wpv+IQfrkVs47IV0U=; b=LGn0YbsKiXH3qYOKga0YXHC9gqvW0Dji/6+Isv/OSlhKiGg55ZbZmbj7msanbp8esOJKEn 3QqaDdW0epGekl4dlgvxKJCVuqiV8SotCz9VIUVX3DpvmcxkhkoRG2K7akefnotu0Z6gjt GZ7S4V2cI4W6TttQ716TlSX1EBCGnho= Received: from mail-ed1-f72.google.com (mail-ed1-f72.google.com [209.85.208.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-133-Ua_LPelZMfuco0t_r3qniQ-1; Fri, 04 Aug 2023 14:24:17 -0400 X-MC-Unique: Ua_LPelZMfuco0t_r3qniQ-1 Received: by mail-ed1-f72.google.com with SMTP id 4fb4d7f45d1cf-522e6bcde75so1568432a12.2 for ; Fri, 04 Aug 2023 11:24:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173456; x=1691778256; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NfuUlvOtQCcgIWDDGRTDaO97w4Wpv+IQfrkVs47IV0U=; b=EB+A8PeoHSzPQoNUPQ2fOtuyGGu/CHXo41iW6J1xy0fJzy8qHeyhcr52/F9J0xaxI4 XR8fVh73AZ455N4hlu8iy5oQgQ1E7KfXAz9UStitaeteUryLYc9wrH9odXP4RVliQNnY w8Gq+q74TfapFeemknfVIUnZGYvMm8OrmcGgHASDfu960hSGlvoKWnA8/65mEhvT8Sfu OVU6oKHOdalU58MvbtBNLBanvjzx9A0o/wP5qZa5+jp9DnUt5euDwp3wkX/v3RuIji6q w/q8Ct7f6ddim5pPgLyGOeO2/FbrWbOyAiyq14+wnJ24GJgeq2X/zDiq3sfAUbsoyOwj tabg== X-Gm-Message-State: AOJu0YzSVBvSYSM5b4yTzZC/t/HBa73TtTU5n9HdTr9Tt4KAlF/DTcOu KkRq+zQfb6icADcDabZEVwFZ5Xq3YKMHACQGDlI2pBsnm91f5acJEJttVxiHwc84QvcA1yzeduT egIa+qje6peIzR7zEjFWT6Tdp X-Received: by 2002:aa7:db44:0:b0:522:3c32:fd2e with SMTP id n4-20020aa7db44000000b005223c32fd2emr2223765edt.24.1691173456653; Fri, 04 Aug 2023 11:24:16 -0700 (PDT) X-Received: by 2002:aa7:db44:0:b0:522:3c32:fd2e with SMTP id n4-20020aa7db44000000b005223c32fd2emr2223746edt.24.1691173456342; Fri, 04 Aug 2023 11:24:16 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id d12-20020aa7ce0c000000b005230724b2b1sm1581545edv.45.2023.08.04.11.24.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:15 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 01/12] drm/gem: fix lockdep check for dma-resv lock Date: Fri, 4 Aug 2023 20:23:41 +0200 Message-ID: <20230804182406.5222-2-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773331875982384399 X-GMAIL-MSGID: 1773331875982384399 When no custom lock is set to protect a GEMs GPUVA list, lockdep checks should fall back to the GEM objects dma-resv lock. With the current implementation we're setting the lock_dep_map of the GEM objects 'resv' pointer (in case no custom lock_dep_map is set yet) on drm_gem_private_object_init(). However, the GEM objects 'resv' pointer might still change after drm_gem_private_object_init() is called, e.g. through ttm_bo_init_reserved(). This can result in the wrong lock being tracked. To fix this, call dma_resv_held() directly from drm_gem_gpuva_assert_lock_held() and fall back to the GEMs lock_dep_map pointer only if an actual custom lock is set. Fixes: e6303f323b1a ("drm: manager to keep track of GPUs VA mappings") Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- include/drm/drm_gem.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index c0b13c43b459..bc9f6aa2f3fe 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -551,15 +551,17 @@ int drm_gem_evict(struct drm_gem_object *obj); * @lock: the lock used to protect the gpuva list. The locking primitive * must contain a dep_map field. * - * Call this if you're not proctecting access to the gpuva list - * with the dma-resv lock, otherwise, drm_gem_gpuva_init() takes care - * of initializing lock_dep_map for you. + * Call this if you're not proctecting access to the gpuva list with the + * dma-resv lock, but with a custom lock. */ #define drm_gem_gpuva_set_lock(obj, lock) \ - if (!(obj)->gpuva.lock_dep_map) \ + if (!WARN((obj)->gpuva.lock_dep_map, \ + "GEM GPUVA lock should be set only once.")) \ (obj)->gpuva.lock_dep_map = &(lock)->dep_map #define drm_gem_gpuva_assert_lock_held(obj) \ - lockdep_assert(lock_is_held((obj)->gpuva.lock_dep_map)) + lockdep_assert((obj)->gpuva.lock_dep_map ? \ + lock_is_held((obj)->gpuva.lock_dep_map) : \ + dma_resv_held((obj)->resv)) #else #define drm_gem_gpuva_set_lock(obj, lock) do {} while (0) #define drm_gem_gpuva_assert_lock_held(obj) do {} while (0) @@ -573,11 +575,12 @@ int drm_gem_evict(struct drm_gem_object *obj); * * Calling this function is only necessary for drivers intending to support the * &drm_driver_feature DRIVER_GEM_GPUVA. + * + * See also drm_gem_gpuva_set_lock(). */ static inline void drm_gem_gpuva_init(struct drm_gem_object *obj) { INIT_LIST_HEAD(&obj->gpuva.list); - drm_gem_gpuva_set_lock(obj, &obj->resv->lock.base); } /** From patchwork Fri Aug 4 18:23:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131331 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp75495vqr; Fri, 4 Aug 2023 13:10:00 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHTLzqMU0oyQK3HXGwRZCJVkwCV8a+xR40IQXNmXd2iy+u16xD/FUjOkSq1wIKtlRnys6ut X-Received: by 2002:aa7:d585:0:b0:523:212e:e4dc with SMTP id r5-20020aa7d585000000b00523212ee4dcmr1520068edq.16.1691179800407; Fri, 04 Aug 2023 13:10:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691179800; cv=none; d=google.com; s=arc-20160816; b=XV0nDuPnM6ZnBGG3MyAOIMmr2kcxGfuefV5AmdMIa5TdjT7i4tHL9LmvJXnTwMRaTs Bta8axPC1U233O/q4R2JTKAyNoW9nQoeinmKeFpHn7Cxa51cft+jZviU6EnFywxjsQty i/jB1SX/tKtF8AyTDYXhEK4sR3ii1xjwvgIOWGM4dZIpAL6/S2gFgX/4Xm7PF/8Ta7TL CbDcAbgQNWxY5iXVJw/oanP9Tk+Xx6YsdF276QlXO7rZimzAPxfFCE8nuQpimWPbX6VO WwqDBLFZjmJpJnc50V3mQQzrYjjLa8Tgzxb+Xwd6B3GyLKoSxOdaZTQJ9et8awX4N4Hj 3FDw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=vYr3+FrZbnstJX6FCxlFaxYgyvWfpTU29Ge9cFia7wg=; fh=BYIBV55vWM0QXS/eY4taDZDQgGwRDrl+zN4PNUHaIjM=; b=UIFAt8wa3LJL1LfVI8m9IgeCC/K+61QGOIW20bjujuEzTm+p0XjUcrMx2gKeHJL3j5 04nZrnwdb7Zzo//q2nz0PK20w6bizb3ub8MxuASMM4Bs9Cp7J4fehF4GaL7Rsl1zH3Lf BefyLrpnjtpUwvtm4pkjpcRMoN+arOsOmHcoNo5RL2dV1Jt0o1Ws3ovPrwGlqAb3BtAm LALchaGL95pyYCMhbbuHwzt76YqQObjvbC5DH/FRLTqfACpk+lcarxewL6jq9h5dM7MW 5MUae/X5cKub0dvkBmAi2uAP4Vm1NiQOc3vQADoDLKJ8kfZvjhvfyTKf3BtylX7zysIS RQeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=jECXY4Mg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f14-20020a50ee8e000000b00523073906f2si1463528edr.536.2023.08.04.13.09.37; Fri, 04 Aug 2023 13:10:00 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=jECXY4Mg; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231474AbjHDSZp (ORCPT + 99 others); Fri, 4 Aug 2023 14:25:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231216AbjHDSZQ (ORCPT ); Fri, 4 Aug 2023 14:25:16 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA56E4C02 for ; Fri, 4 Aug 2023 11:24:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173466; 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=vYr3+FrZbnstJX6FCxlFaxYgyvWfpTU29Ge9cFia7wg=; b=jECXY4MgnaWFXvLR49J7GpH5++twtT52nNCEOb8ntMFWVVm+7WGah4MOJ5eu5xfOpmRbh7 sq/6f49lpAZA/C5UxXYe+/ddKjSUa0amd8qOpr/EOYMsNdt0mpuFwGxk/wdsnZuH59BUKF LwJS3hMiTjTEIuF1sdqv4uVhWLM/32c= Received: from mail-ed1-f71.google.com (mail-ed1-f71.google.com [209.85.208.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-284-u6hJJtjePemo-vpZAKoslw-1; Fri, 04 Aug 2023 14:24:22 -0400 X-MC-Unique: u6hJJtjePemo-vpZAKoslw-1 Received: by mail-ed1-f71.google.com with SMTP id 4fb4d7f45d1cf-5223854ef71so1574986a12.1 for ; Fri, 04 Aug 2023 11:24:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173461; x=1691778261; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vYr3+FrZbnstJX6FCxlFaxYgyvWfpTU29Ge9cFia7wg=; b=Q+cNROIf6JIbvA7W7/rq12lYui09kRVNAG3WccIM9aLEb9FgrSvhUIx/v05xJwo3E9 81NcZ3lN+p/BdpGUg8SIu1nc94bV9JwgeETbJGO28HawnTPzyr+0eFXU9oC7v2ZjQs0E HGDeNmsbuePMJlSsvUKgiTpZ8W5irXj7rqjnTs1ZGNfOX+4nsB/VFRJ9UZ7ZzRB4KWb5 477Wq7JFYd9IVYnOXQEgyrh41Jt+RNCArO5me0VXfD6Ut+xidcX3EIi2DJwAoSxcZPh/ 1hNA7WlqydQDtYKrDCUiPAyqJZuTOeN/F8XIyI86euVZwNVQMwdEZqdArRf3NbjwA0Ex f6tg== X-Gm-Message-State: AOJu0YxnD2mOTm11lM2CTyoQYiVPEph3T2sZsi5i5ISW9UXMaUBmrpUf dz4l1EPfR7kdeNBvzAMbf2FQoi+7nfNi2TFqKiix0KD0JJlVtSLPgONddtqI1DTMsheiBsa+mb0 5A/unyHv6RfNTvcMv4yLhV2WP X-Received: by 2002:aa7:c7cf:0:b0:522:cc6c:e25e with SMTP id o15-20020aa7c7cf000000b00522cc6ce25emr2173053eds.3.1691173460976; Fri, 04 Aug 2023 11:24:20 -0700 (PDT) X-Received: by 2002:aa7:c7cf:0:b0:522:cc6c:e25e with SMTP id o15-20020aa7c7cf000000b00522cc6ce25emr2173047eds.3.1691173460822; Fri, 04 Aug 2023 11:24:20 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id d13-20020a50fe8d000000b0051e1660a34esm1557805edt.51.2023.08.04.11.24.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:20 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Dave Airlie , Faith Ekstrand , Danilo Krummrich Subject: [PATCH drm-misc-next v10 02/12] drm/nouveau: fixup the uapi header file. Date: Fri, 4 Aug 2023 20:23:42 +0200 Message-ID: <20230804182406.5222-3-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773330550048233962 X-GMAIL-MSGID: 1773330550048233962 From: Dave Airlie nouveau > 10 years ago had a plan for new multiplexer inside a multiplexer API using nvif. It never fully reached fruition, fast forward 10 years, and the new vulkan driver is avoiding libdrm and calling ioctls, and these 3 ioctls, getparam, channel alloc + free don't seem to be things we'd want to use nvif for. Undeprecate and put them into the uapi header so we can just copy it into mesa later. v2: use uapi types. Reviewed-by: Faith Ekstrand Signed-off-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_abi16.h | 41 --------------------- include/uapi/drm/nouveau_drm.h | 48 +++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index 27eae85f33e6..d5d80d0d9011 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -43,28 +43,6 @@ int nouveau_abi16_usif(struct drm_file *, void *data, u32 size); #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) -struct drm_nouveau_channel_alloc { - uint32_t fb_ctxdma_handle; - uint32_t tt_ctxdma_handle; - - int channel; - uint32_t pushbuf_domains; - - /* Notifier memory */ - uint32_t notifier_handle; - - /* DRM-enforced subchannel assignments */ - struct { - uint32_t handle; - uint32_t grclass; - } subchan[8]; - uint32_t nr_subchan; -}; - -struct drm_nouveau_channel_free { - int channel; -}; - struct drm_nouveau_grobj_alloc { int channel; uint32_t handle; @@ -83,31 +61,12 @@ struct drm_nouveau_gpuobj_free { uint32_t handle; }; -#define NOUVEAU_GETPARAM_PCI_VENDOR 3 -#define NOUVEAU_GETPARAM_PCI_DEVICE 4 -#define NOUVEAU_GETPARAM_BUS_TYPE 5 -#define NOUVEAU_GETPARAM_FB_SIZE 8 -#define NOUVEAU_GETPARAM_AGP_SIZE 9 -#define NOUVEAU_GETPARAM_CHIPSET_ID 11 -#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 -#define NOUVEAU_GETPARAM_GRAPH_UNITS 13 -#define NOUVEAU_GETPARAM_PTIMER_TIME 14 -#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 -#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 -struct drm_nouveau_getparam { - uint64_t param; - uint64_t value; -}; - struct drm_nouveau_setparam { uint64_t param; uint64_t value; }; -#define DRM_IOCTL_NOUVEAU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam) #define DRM_IOCTL_NOUVEAU_SETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SETPARAM, struct drm_nouveau_setparam) -#define DRM_IOCTL_NOUVEAU_CHANNEL_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_ALLOC, struct drm_nouveau_channel_alloc) -#define DRM_IOCTL_NOUVEAU_CHANNEL_FREE DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_FREE, struct drm_nouveau_channel_free) #define DRM_IOCTL_NOUVEAU_GROBJ_ALLOC DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GROBJ_ALLOC, struct drm_nouveau_grobj_alloc) #define DRM_IOCTL_NOUVEAU_NOTIFIEROBJ_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, struct drm_nouveau_notifierobj_alloc) #define DRM_IOCTL_NOUVEAU_GPUOBJ_FREE DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GPUOBJ_FREE, struct drm_nouveau_gpuobj_free) diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h index 853a327433d3..ca917e55b38f 100644 --- a/include/uapi/drm/nouveau_drm.h +++ b/include/uapi/drm/nouveau_drm.h @@ -33,6 +33,44 @@ extern "C" { #endif +#define NOUVEAU_GETPARAM_PCI_VENDOR 3 +#define NOUVEAU_GETPARAM_PCI_DEVICE 4 +#define NOUVEAU_GETPARAM_BUS_TYPE 5 +#define NOUVEAU_GETPARAM_FB_SIZE 8 +#define NOUVEAU_GETPARAM_AGP_SIZE 9 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 +#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 +#define NOUVEAU_GETPARAM_GRAPH_UNITS 13 +#define NOUVEAU_GETPARAM_PTIMER_TIME 14 +#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 +#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 +struct drm_nouveau_getparam { + __u64 param; + __u64 value; +}; + +struct drm_nouveau_channel_alloc { + __u32 fb_ctxdma_handle; + __u32 tt_ctxdma_handle; + + __s32 channel; + __u32 pushbuf_domains; + + /* Notifier memory */ + __u32 notifier_handle; + + /* DRM-enforced subchannel assignments */ + struct { + __u32 handle; + __u32 grclass; + } subchan[8]; + __u32 nr_subchan; +}; + +struct drm_nouveau_channel_free { + __s32 channel; +}; + #define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) @@ -126,10 +164,10 @@ struct drm_nouveau_gem_cpu_fini { __u32 handle; }; -#define DRM_NOUVEAU_GETPARAM 0x00 /* deprecated */ +#define DRM_NOUVEAU_GETPARAM 0x00 #define DRM_NOUVEAU_SETPARAM 0x01 /* deprecated */ -#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 /* deprecated */ -#define DRM_NOUVEAU_CHANNEL_FREE 0x03 /* deprecated */ +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 +#define DRM_NOUVEAU_CHANNEL_FREE 0x03 #define DRM_NOUVEAU_GROBJ_ALLOC 0x04 /* deprecated */ #define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 /* deprecated */ #define DRM_NOUVEAU_GPUOBJ_FREE 0x06 /* deprecated */ @@ -188,6 +226,10 @@ struct drm_nouveau_svm_bind { #define NOUVEAU_SVM_BIND_TARGET__GPU_VRAM (1UL << 31) +#define DRM_IOCTL_NOUVEAU_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GETPARAM, struct drm_nouveau_getparam) +#define DRM_IOCTL_NOUVEAU_CHANNEL_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_ALLOC, struct drm_nouveau_channel_alloc) +#define DRM_IOCTL_NOUVEAU_CHANNEL_FREE DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_CHANNEL_FREE, struct drm_nouveau_channel_free) + #define DRM_IOCTL_NOUVEAU_SVM_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SVM_INIT, struct drm_nouveau_svm_init) #define DRM_IOCTL_NOUVEAU_SVM_BIND DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SVM_BIND, struct drm_nouveau_svm_bind) From patchwork Fri Aug 4 18:23:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131332 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp75606vqr; Fri, 4 Aug 2023 13:10:13 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFOTbJhUJl76FBFBC1y4/iGtQPrtXCY5GHyRHDWI7PlbwbyDnNErUAppFki8f0gn556rZgV X-Received: by 2002:a2e:964e:0:b0:2b7:31a:9d7c with SMTP id z14-20020a2e964e000000b002b7031a9d7cmr2429071ljh.33.1691179813047; Fri, 04 Aug 2023 13:10:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691179813; cv=none; d=google.com; s=arc-20160816; b=AaRjGp92ZblKP0HffN7uO12Kk+CpsT/97Y6iwvbkwdjlqybQ/P90Eo0ZwZrBGD1S1R K1sr2FR/9wh3331aLrbUbaL5GprrVworNprILQ2ekf/jmuPQgtmBdlEuluPjpd0rdhAc PeQZ1UHbcQAMW+8tzAOlFtjVxRpkjO6WkL71DvypKBkx3zPKzHhQck/SDGBNuPDqnGey PTr/htPrnSSuPQ3cOnpQTGybdN5OJfLJv7HmyBvSPS0Tar21IzR6YTiLBTjCEHJxtFGy iQGe2FMNGOFZvtoOSVa1S03/4+n+UOUtx/VOUwQ1oTEtMLOPkh2GF03PSmijbZ4HsWwj MwfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=tdvB6S+0xdJe+R0RQa7YvMStrYjQLCLaAmPE3m6irHk=; fh=2pmUVqUvotSH7CB+6zW0KwsQpw04eJYZ+XQeoH/QedI=; b=MI1JDrjUWPUy3v+ZRLnZcgyFCfF2ng8F6JEWwjUwqDF64vyR604U2iSOZpxQdKbdqV P9dbPImFwc2jIiuWdMGCJM38+3WLSN+zzJIg+7MpsHEGBTNW7nSwc//LG2sQL6AiJ8zM DbbqgM6lDWldokn/14VOhqib0RV1ndmZ5p6eru2nP30Nq+BmQetjPx+/UHkOnBWHaBs0 yNDNVhxSiOlm+QW4hDmjarK4yTCxDgS2CffKU+zuytgdkTo+pQpwx88LcHPUk3mqV4WB Xy2LCovW9O/CoTCr49/y2OUjr5sjH5gRH3KGHJla+nMDAMrGnGHvxATdsHVMWh0zbCRr op7g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=SpnA6Fse; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t3-20020a170906178300b009938248d370si2142737eje.2.2023.08.04.13.09.49; Fri, 04 Aug 2023 13:10:13 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=SpnA6Fse; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231376AbjHDSZv (ORCPT + 99 others); Fri, 4 Aug 2023 14:25:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231314AbjHDSZS (ORCPT ); Fri, 4 Aug 2023 14:25:18 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E3E244C0D for ; Fri, 4 Aug 2023 11:24:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173468; 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=tdvB6S+0xdJe+R0RQa7YvMStrYjQLCLaAmPE3m6irHk=; b=SpnA6FseI6/Z753OpoxUSJEBWmCwQqPeabM06U+LtqNcveFNGahDQ5XIkKWfP3QZlqvTo/ /PM6QwY7l16uC+c4XW1b9+VQ9wiGEwQMvaH2UG4hFzPh0Ax//jzZmIwoNn5WqWsU5wGisr Su22nelKgXQvkEbs6YQBm9dtQg2c7Uc= Received: from mail-ej1-f70.google.com (mail-ej1-f70.google.com [209.85.218.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-264-mgLrPZ_iMIiNjTlAZAU15A-1; Fri, 04 Aug 2023 14:24:26 -0400 X-MC-Unique: mgLrPZ_iMIiNjTlAZAU15A-1 Received: by mail-ej1-f70.google.com with SMTP id a640c23a62f3a-99bcfdaaa52so162199966b.0 for ; Fri, 04 Aug 2023 11:24:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173465; x=1691778265; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tdvB6S+0xdJe+R0RQa7YvMStrYjQLCLaAmPE3m6irHk=; b=MARu14F4M8XFIUYo5otzDQmzetLqKgjq0zO5uWmBTV/wj3kcgg6cuidpZc1cVODfEg +P3GdSXw4eLsp0y4zTSw1TixDsLPuBit5wYktGiDUDohPjstUOSuIL8JoNChx3Wn8x2Y cE9fX+auakRgD98efO6Q6pQ7y3Ibrbz7RQHtMjxezTJTnUqqwwKKv249c/Hh/pmclzSS 1r72bckjwRXDAOsadiBIPDjMKKvzsBEJdthGN12TerLGctVV09zsT/+AO5yJpnMYDupR hj9vlseO+2YK7rjL5FIJfwZPQVtMFHl+MOXjv8F0noDnslbIwKWORBk+zzTPgqLZcF14 ngrg== X-Gm-Message-State: AOJu0YzzjRrCJ1AY++EqKZOj5pDNwrALIl4r2/Qk/BgBLw1hjn30luPX YximkCr51QSHl1FWS4z3RN+K7R/zDap0cVNOzIug2gETXaa2iacotJtGMQDnc7dI0wH6ZB550GA YTR6a9JSpT0+cgW23LCqESUHg X-Received: by 2002:a17:906:54:b0:99b:44aa:fae0 with SMTP id 20-20020a170906005400b0099b44aafae0mr2198335ejg.21.1691173465554; Fri, 04 Aug 2023 11:24:25 -0700 (PDT) X-Received: by 2002:a17:906:54:b0:99b:44aa:fae0 with SMTP id 20-20020a170906005400b0099b44aafae0mr2198317ejg.21.1691173465346; Fri, 04 Aug 2023 11:24:25 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id h4-20020a1709062dc400b0099bc2d1429csm1642676eji.72.2023.08.04.11.24.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:24 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Faith Ekstrand , Dave Airlie Subject: [PATCH drm-misc-next v10 03/12] drm/nouveau: new VM_BIND uAPI interfaces Date: Fri, 4 Aug 2023 20:23:43 +0200 Message-ID: <20230804182406.5222-4-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773330563492160049 X-GMAIL-MSGID: 1773330563492160049 This commit provides the interfaces for the new UAPI motivated by the Vulkan API. It allows user mode drivers (UMDs) to: 1) Initialize a GPU virtual address (VA) space via the new DRM_IOCTL_NOUVEAU_VM_INIT ioctl. UMDs can provide a kernel reserved VA area. 2) Bind and unbind GPU VA space mappings via the new DRM_IOCTL_NOUVEAU_VM_BIND ioctl. 3) Execute push buffers with the new DRM_IOCTL_NOUVEAU_EXEC ioctl. Both, DRM_IOCTL_NOUVEAU_VM_BIND and DRM_IOCTL_NOUVEAU_EXEC support asynchronous processing with DRM syncobjs as synchronization mechanism. The default DRM_IOCTL_NOUVEAU_VM_BIND is synchronous processing, DRM_IOCTL_NOUVEAU_EXEC supports asynchronous processing only. Reviewed-by: Faith Ekstrand Reviewed-by: Dave Airlie Co-developed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- Documentation/gpu/driver-uapi.rst | 8 ++ include/uapi/drm/nouveau_drm.h | 217 ++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst index 4411e6919a3d..9c7ca6e33a68 100644 --- a/Documentation/gpu/driver-uapi.rst +++ b/Documentation/gpu/driver-uapi.rst @@ -6,3 +6,11 @@ drm/i915 uAPI ============= .. kernel-doc:: include/uapi/drm/i915_drm.h + +drm/nouveau uAPI +================ + +VM_BIND / EXEC uAPI +------------------- + +.. kernel-doc:: include/uapi/drm/nouveau_drm.h diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h index ca917e55b38f..b1ad9d5ffce8 100644 --- a/include/uapi/drm/nouveau_drm.h +++ b/include/uapi/drm/nouveau_drm.h @@ -76,6 +76,8 @@ struct drm_nouveau_channel_free { #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) #define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) #define NOUVEAU_GEM_DOMAIN_COHERENT (1 << 4) +/* The BO will never be shared via import or export. */ +#define NOUVEAU_GEM_DOMAIN_NO_SHARE (1 << 5) #define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */ #define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 @@ -164,6 +166,215 @@ struct drm_nouveau_gem_cpu_fini { __u32 handle; }; +/** + * struct drm_nouveau_sync - sync object + * + * This structure serves as synchronization mechanism for (potentially) + * asynchronous operations such as EXEC or VM_BIND. + */ +struct drm_nouveau_sync { + /** + * @flags: the flags for a sync object + * + * The first 8 bits are used to determine the type of the sync object. + */ + __u32 flags; +#define DRM_NOUVEAU_SYNC_SYNCOBJ 0x0 +#define DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ 0x1 +#define DRM_NOUVEAU_SYNC_TYPE_MASK 0xf + /** + * @handle: the handle of the sync object + */ + __u32 handle; + /** + * @timeline_value: + * + * The timeline point of the sync object in case the syncobj is of + * type DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ. + */ + __u64 timeline_value; +}; + +/** + * struct drm_nouveau_vm_init - GPU VA space init structure + * + * Used to initialize the GPU's VA space for a user client, telling the kernel + * which portion of the VA space is managed by the UMD and kernel respectively. + * + * For the UMD to use the VM_BIND uAPI, this must be called before any BOs or + * channels are created; if called afterwards DRM_IOCTL_NOUVEAU_VM_INIT fails + * with -ENOSYS. + */ +struct drm_nouveau_vm_init { + /** + * @kernel_managed_addr: start address of the kernel managed VA space + * region + */ + __u64 kernel_managed_addr; + /** + * @kernel_managed_size: size of the kernel managed VA space region in + * bytes + */ + __u64 kernel_managed_size; +}; + +/** + * struct drm_nouveau_vm_bind_op - VM_BIND operation + * + * This structure represents a single VM_BIND operation. UMDs should pass + * an array of this structure via struct drm_nouveau_vm_bind's &op_ptr field. + */ +struct drm_nouveau_vm_bind_op { + /** + * @op: the operation type + */ + __u32 op; +/** + * @DRM_NOUVEAU_VM_BIND_OP_MAP: + * + * Map a GEM object to the GPU's VA space. Optionally, the + * &DRM_NOUVEAU_VM_BIND_SPARSE flag can be passed to instruct the kernel to + * create sparse mappings for the given range. + */ +#define DRM_NOUVEAU_VM_BIND_OP_MAP 0x0 +/** + * @DRM_NOUVEAU_VM_BIND_OP_UNMAP: + * + * Unmap an existing mapping in the GPU's VA space. If the region the mapping + * is located in is a sparse region, new sparse mappings are created where the + * unmapped (memory backed) mapping was mapped previously. To remove a sparse + * region the &DRM_NOUVEAU_VM_BIND_SPARSE must be set. + */ +#define DRM_NOUVEAU_VM_BIND_OP_UNMAP 0x1 + /** + * @flags: the flags for a &drm_nouveau_vm_bind_op + */ + __u32 flags; +/** + * @DRM_NOUVEAU_VM_BIND_SPARSE: + * + * Indicates that an allocated VA space region should be sparse. + */ +#define DRM_NOUVEAU_VM_BIND_SPARSE (1 << 8) + /** + * @handle: the handle of the DRM GEM object to map + */ + __u32 handle; + /** + * @pad: 32 bit padding, should be 0 + */ + __u32 pad; + /** + * @addr: + * + * the address the VA space region or (memory backed) mapping should be mapped to + */ + __u64 addr; + /** + * @bo_offset: the offset within the BO backing the mapping + */ + __u64 bo_offset; + /** + * @range: the size of the requested mapping in bytes + */ + __u64 range; +}; + +/** + * struct drm_nouveau_vm_bind - structure for DRM_IOCTL_NOUVEAU_VM_BIND + */ +struct drm_nouveau_vm_bind { + /** + * @op_count: the number of &drm_nouveau_vm_bind_op + */ + __u32 op_count; + /** + * @flags: the flags for a &drm_nouveau_vm_bind ioctl + */ + __u32 flags; +/** + * @DRM_NOUVEAU_VM_BIND_RUN_ASYNC: + * + * Indicates that the given VM_BIND operation should be executed asynchronously + * by the kernel. + * + * If this flag is not supplied the kernel executes the associated operations + * synchronously and doesn't accept any &drm_nouveau_sync objects. + */ +#define DRM_NOUVEAU_VM_BIND_RUN_ASYNC 0x1 + /** + * @wait_count: the number of wait &drm_nouveau_syncs + */ + __u32 wait_count; + /** + * @sig_count: the number of &drm_nouveau_syncs to signal when finished + */ + __u32 sig_count; + /** + * @wait_ptr: pointer to &drm_nouveau_syncs to wait for + */ + __u64 wait_ptr; + /** + * @sig_ptr: pointer to &drm_nouveau_syncs to signal when finished + */ + __u64 sig_ptr; + /** + * @op_ptr: pointer to the &drm_nouveau_vm_bind_ops to execute + */ + __u64 op_ptr; +}; + +/** + * struct drm_nouveau_exec_push - EXEC push operation + * + * This structure represents a single EXEC push operation. UMDs should pass an + * array of this structure via struct drm_nouveau_exec's &push_ptr field. + */ +struct drm_nouveau_exec_push { + /** + * @va: the virtual address of the push buffer mapping + */ + __u64 va; + /** + * @va_len: the length of the push buffer mapping + */ + __u64 va_len; +}; + +/** + * struct drm_nouveau_exec - structure for DRM_IOCTL_NOUVEAU_EXEC + */ +struct drm_nouveau_exec { + /** + * @channel: the channel to execute the push buffer in + */ + __u32 channel; + /** + * @push_count: the number of &drm_nouveau_exec_push ops + */ + __u32 push_count; + /** + * @wait_count: the number of wait &drm_nouveau_syncs + */ + __u32 wait_count; + /** + * @sig_count: the number of &drm_nouveau_syncs to signal when finished + */ + __u32 sig_count; + /** + * @wait_ptr: pointer to &drm_nouveau_syncs to wait for + */ + __u64 wait_ptr; + /** + * @sig_ptr: pointer to &drm_nouveau_syncs to signal when finished + */ + __u64 sig_ptr; + /** + * @push_ptr: pointer to &drm_nouveau_exec_push ops + */ + __u64 push_ptr; +}; + #define DRM_NOUVEAU_GETPARAM 0x00 #define DRM_NOUVEAU_SETPARAM 0x01 /* deprecated */ #define DRM_NOUVEAU_CHANNEL_ALLOC 0x02 @@ -174,6 +385,9 @@ struct drm_nouveau_gem_cpu_fini { #define DRM_NOUVEAU_NVIF 0x07 #define DRM_NOUVEAU_SVM_INIT 0x08 #define DRM_NOUVEAU_SVM_BIND 0x09 +#define DRM_NOUVEAU_VM_INIT 0x10 +#define DRM_NOUVEAU_VM_BIND 0x11 +#define DRM_NOUVEAU_EXEC 0x12 #define DRM_NOUVEAU_GEM_NEW 0x40 #define DRM_NOUVEAU_GEM_PUSHBUF 0x41 #define DRM_NOUVEAU_GEM_CPU_PREP 0x42 @@ -239,6 +453,9 @@ struct drm_nouveau_svm_bind { #define DRM_IOCTL_NOUVEAU_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_FINI, struct drm_nouveau_gem_cpu_fini) #define DRM_IOCTL_NOUVEAU_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_INFO, struct drm_nouveau_gem_info) +#define DRM_IOCTL_NOUVEAU_VM_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_VM_INIT, struct drm_nouveau_vm_init) +#define DRM_IOCTL_NOUVEAU_VM_BIND DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_VM_BIND, struct drm_nouveau_vm_bind) +#define DRM_IOCTL_NOUVEAU_EXEC DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_EXEC, struct drm_nouveau_exec) #if defined(__cplusplus) } #endif From patchwork Fri Aug 4 18:23:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131336 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp77252vqr; Fri, 4 Aug 2023 13:13:45 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHvNTSXVU3xJHfWGJ56tPrGE1XkgzfEQ2CShpKUrTQ+m2eBm+vLbVb6e/KfBv+pnet7ZCs5 X-Received: by 2002:aa7:d318:0:b0:522:ae79:3ee8 with SMTP id p24-20020aa7d318000000b00522ae793ee8mr2566957edq.5.1691180025136; Fri, 04 Aug 2023 13:13:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691180025; cv=none; d=google.com; s=arc-20160816; b=Fscon/uCG1K0LRCUDKLVj9Q3Qb/h34f8uM/6J9rh7nLUegK8HdOopUHyK5sxQpphSg dux8YqqMuh+QoOzZOEcOhGvioaHrpYDNsQfCNIGelCbQcjIwMR+nhm3tuPts8PkWczWU lSaDHRmm2xRQZxcvG2N3MCRx9y+e7LI27YrUGKunws6lnz2oWDMLZkHRuXLAiZKGe6Ln GO+3zcfWtQDpaJuS+D4QlS03M7Q5coZbda9vv0gIskxVLIABsivnYIIQ5Jrco/yUqzzM nyijRg5UWK+FexofxHMf1MZiIOCA/sBrWS/47hWMSMmJQ9SKVz3upBzf4x8tGWyl87z9 eqEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=emComDzbbyqXVFHSmzoRBucD9FYG4LZk4alPAnUvQUs=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=cJ3xQBVKo7TLtxpmOkEP8yo6MzbbtTVGWswtk4BLDlmivPWTdKj8HXyWuVWLtfaMvr zyWkC4id2J9zMmY7sbfUsC1SRQAdF0V7VijXB6ZAu8SZYwOUbOLIYONY0vks+NwwWAL6 qKEivJOTvYrf+rOVD3Rs817sHuk9gULtt0u8vMZZs59qH+IhHppcDYJR3Tx98zjEg7GQ pB5CUzXiWwjA0cfYoGWYAVURY9F5rEBS4eKRMyfjEdMKlYLsFNCDdGe3y7GlCbpdJgDV 8JGuY/K7ZM2nWU82ucLtx+nIXnIEpCsXXZLluybCr/NqxHxtxCQCJuQ4nThWxqI+pFlf ERsg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Sakhc7Rr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b23-20020aa7d497000000b005220ee1fe53si1124692edr.510.2023.08.04.13.13.21; Fri, 04 Aug 2023 13:13:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Sakhc7Rr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231408AbjHDS0W (ORCPT + 99 others); Fri, 4 Aug 2023 14:26:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53222 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230522AbjHDSZ3 (ORCPT ); Fri, 4 Aug 2023 14:25:29 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A80A04ECA for ; Fri, 4 Aug 2023 11:24:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173472; 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=emComDzbbyqXVFHSmzoRBucD9FYG4LZk4alPAnUvQUs=; b=Sakhc7RrwzRyifUmNn3qeAMzIsF+pCbKBMMz3BcQ8Hd42YAy79WNgbEBiuqPWNmAlOqlCn HxnXpYiKrV0VE+iibSpZdzPyhbZqK2dusrQdaXbVkr89Bjb9IfsdQlPj1JUMToCUYyKv1q KM2oE5xWhirpb67mqckBsksDvlmBzkQ= Received: from mail-ej1-f72.google.com (mail-ej1-f72.google.com [209.85.218.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-392-s_NSbq2UPnOeiDvvsKNN_A-1; Fri, 04 Aug 2023 14:24:31 -0400 X-MC-Unique: s_NSbq2UPnOeiDvvsKNN_A-1 Received: by mail-ej1-f72.google.com with SMTP id a640c23a62f3a-99388334de6so195880866b.0 for ; Fri, 04 Aug 2023 11:24:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173470; x=1691778270; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=emComDzbbyqXVFHSmzoRBucD9FYG4LZk4alPAnUvQUs=; b=kR/hwESgqUO10vKrMn8rL0tc3h6Jceg2WR6WPzGYCUypqRcoffPiD5/TDjEU4nB4NZ vzkb93dEG4jd773jpnMg9trSYa4spYmdYb0DYg83Ordyas75yfv2haYQh8SkHxUEj0U8 jkM8OuV93tmG4ZgAnz2qXTQH3R7Dr5BPx8erYF2i+j2qw4fsU3vhtfg8p1uP9BVMSt0l bLFdmS7/dN+F9rad5T8E3p+iwn6bYjaUVLy/WzwBqV137YWIaua1nugpd3PYalkGaNQH c6GimCbtCEka8+FsqAe+8Kg+l92uoLhJWFQlRvZYnws8PWKnU/vGkgc08zhsbIViZd/r /lMA== X-Gm-Message-State: AOJu0Yz9lOGXoZQU9IH5KvF9uz/UhXYmhU6q1IHzm0S5kl9mgvxW2peB 75u4ELoTcbMASwywy5NqtLTdfMVN7Lpah24C+YitaAU4kx9GnbLWpWtjztX4OjTl8qpwZrfRJyC Z82/fMYz0joybLYfdAihIq/xV X-Received: by 2002:a17:907:a058:b0:99b:bbe:e232 with SMTP id gz24-20020a170907a05800b0099b0bbee232mr1939551ejc.68.1691173470393; Fri, 04 Aug 2023 11:24:30 -0700 (PDT) X-Received: by 2002:a17:907:a058:b0:99b:bbe:e232 with SMTP id gz24-20020a170907a05800b0099b0bbee232mr1939529ejc.68.1691173469780; Fri, 04 Aug 2023 11:24:29 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id ch25-20020a170906c2d900b0098d2f703408sm1626455ejb.118.2023.08.04.11.24.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:29 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 04/12] drm/nouveau: get vmm via nouveau_cli_vmm() Date: Fri, 4 Aug 2023 20:23:44 +0200 Message-ID: <20230804182406.5222-5-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773330785812279241 X-GMAIL-MSGID: 1773330785812279241 Provide a getter function for the client's current vmm context. Since we'll add a new (u)vmm context for UMD bindings in subsequent commits, this will keep the code clean. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- drivers/gpu/drm/nouveau/nouveau_chan.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 9 +++++++++ drivers/gpu/drm/nouveau/nouveau_gem.c | 6 +++--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index c2ec91cc845d..7724fe63067d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -204,7 +204,7 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, struct nouveau_drm *drm = cli->drm; struct nouveau_bo *nvbo; struct nvif_mmu *mmu = &cli->mmu; - struct nvif_vmm *vmm = cli->svm.cli ? &cli->svm.vmm : &cli->vmm.vmm; + struct nvif_vmm *vmm = &nouveau_cli_vmm(cli)->vmm; int i, pi = -1; if (!*size) { diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 3dfbc374478e..6d639314250a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -149,7 +149,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, chan->device = device; chan->drm = drm; - chan->vmm = cli->svm.cli ? &cli->svm : &cli->vmm; + chan->vmm = nouveau_cli_vmm(cli); atomic_set(&chan->killed, 0); /* allocate memory for dma push buffer */ diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b5de312a523f..81350e685b50 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -112,6 +112,15 @@ struct nouveau_cli_work { struct dma_fence_cb cb; }; +static inline struct nouveau_vmm * +nouveau_cli_vmm(struct nouveau_cli *cli) +{ + if (cli->svm.cli) + return &cli->svm; + + return &cli->vmm; +} + void nouveau_cli_work_queue(struct nouveau_cli *, struct dma_fence *, struct nouveau_cli_work *); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index ab9062e50977..45ca4eb98f54 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -103,7 +103,7 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct device *dev = drm->dev->dev; - struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm; + struct nouveau_vmm *vmm = nouveau_cli_vmm(cli); struct nouveau_vma *vma; int ret; @@ -180,7 +180,7 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct device *dev = drm->dev->dev; - struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : & cli->vmm; + struct nouveau_vmm *vmm = nouveau_cli_vmm(cli); struct nouveau_vma *vma; int ret; @@ -269,7 +269,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); - struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm; + struct nouveau_vmm *vmm = nouveau_cli_vmm(cli); struct nouveau_vma *vma; if (is_power_of_2(nvbo->valid_domains)) From patchwork Fri Aug 4 18:23:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131309 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp44824vqr; Fri, 4 Aug 2023 12:08:35 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFccCCmPBfdCKei8aP+N55DNKKaOVaYBjk/FLIxAifCyQ/q9jZL1HLBk+tXDsfOt0RR6D3T X-Received: by 2002:a17:903:22cf:b0:1b8:8dbd:e1a0 with SMTP id y15-20020a17090322cf00b001b88dbde1a0mr2835491plg.13.1691176115573; Fri, 04 Aug 2023 12:08:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691176115; cv=none; d=google.com; s=arc-20160816; b=XJmBd5zwZC0GyRDaqUv9YRm1enYjEucgtSYl56AJrKF0x0zZpo3fqUjp+Wl6qVSG2G I1EO+x5VSMYlG9sdgKZzVlJ7gRx3O6aUGCRbsjbl2OuE6nc6Hqc6fzmntO6q28LGDcbG VwZ+BHU3Nu813XjqoOxA9RRXDSSvJGdnwf+nFHtJ4KaqZQ9kv4Pc7oeGQycd5HmbcnCz 7rtJPet53ibzayAAroraFMk9qIDjsf/0UvuMnqdr/dgK8xoWXVOKSCstNlTlcFkc+VkG y94C/tBKjoAe4rmWAQRLBgG1wMPKLMsWy60kapb4NDdW9GUDJe+wVPtH/qjdUq3JOg5i wXLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=uwdeGZqElHaeNok5koZwxqm81zQwPAs60eGGyV3zg50=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=IEBzQqdQ36zaRz/vz2vMSptqkTw4h0UNqYAyAUOx97yOa2GwTKYVYxw8uDycyDrHZ9 nzY+IRdEmL6VPsN7Aex0l3WAlADIcgDyfLlAVImYv8TYOEvtXL9m4Avn2G1NnVPZpKFQ opt6pWDNGIwqekJXhod8compfd84ND3s+jlRawAR3Dm/pMD/SN06yTiUoz6BrQgw4hjz +UKJbCi1d6/8+zr+RwFp+SZdRJszKMvkiFwpIiAsDlDBdmJOySwbPnzhYvlyBpJjfevq obiEWNvc8b0oxvg9SIPRW6I/gzoutnLjR3gIzvEasT79Gn6Xz5tFqjiFmfA68/Edbush fKUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=cqrCIuN9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d16-20020a170903231000b001b3d6d125f9si521847plh.524.2023.08.04.12.08.08; Fri, 04 Aug 2023 12:08:35 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=cqrCIuN9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230241AbjHDS0a (ORCPT + 99 others); Fri, 4 Aug 2023 14:26:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231405AbjHDSZ3 (ORCPT ); Fri, 4 Aug 2023 14:25:29 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EEA334C04 for ; Fri, 4 Aug 2023 11:24:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173476; 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=uwdeGZqElHaeNok5koZwxqm81zQwPAs60eGGyV3zg50=; b=cqrCIuN9WrqKmQzuqf8/N+1GCEgNJWvPj1CF3QOWTcHlv9G5LIL8BL6Ux+yyK5lN4jTsk+ 7MmSWIcg4IBJcORNIrZiSjawKuINVNG7qo9hOGAGMXT6HvGwDl6+gHTEqVUMJzCfMDZhbB T7xW/y1gSjnQ9DPz2xPkGJMQ17Ey6K8= Received: from mail-ej1-f71.google.com (mail-ej1-f71.google.com [209.85.218.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-210-wcjsmUsfPhKYrhRVopyUYQ-1; Fri, 04 Aug 2023 14:24:35 -0400 X-MC-Unique: wcjsmUsfPhKYrhRVopyUYQ-1 Received: by mail-ej1-f71.google.com with SMTP id a640c23a62f3a-99bd6ea0d9eso161305866b.3 for ; Fri, 04 Aug 2023 11:24:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173474; x=1691778274; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uwdeGZqElHaeNok5koZwxqm81zQwPAs60eGGyV3zg50=; b=S+W5UnRJExHXjP0zps/VkGQ1ovtRn5lih+cTER2MvkuDi81pEOBsi2u3JhjEKOutYm AStHyeZJF3DuNyEIDTIGw0mt+1u4p7AaebYIoWI73W794zoUksXIupas2Ip261Ho69YU XS5jxNim2eaS3xKMTafTUYWEIQvqgXWrwv4csvKDJnqajsH/+3uCwhQDAO9Ddtsk1vC6 tKH22SQGEEontqnwCgQo0yXMemr/E4NIKbADA/nJlyX23vl3Ou0gUOrERAscoqXcHCeT vvctzLsdKMm3lrZ4SmpPDw2aJOKjk8rwzNy9yGo1uxdJLgCEeqrV3g3bJFngTID1v0zh 7ypQ== X-Gm-Message-State: AOJu0YyMFRRq2hwUn9mh06s1kQlwdxE9JbykoCvraQNA468JAAOnq4ah FVot4Wb3DvCbsBdv55JOeAMUowRC5d0xftVC8URWbV2qzA3A9QSupQvoyzpaPAbE57xi5FQFT5M kTiKQN1ThpvEaBXBxvfAlA+5M X-Received: by 2002:a17:906:5a5c:b0:99b:65fa:e30f with SMTP id my28-20020a1709065a5c00b0099b65fae30fmr2089714ejc.1.1691173474214; Fri, 04 Aug 2023 11:24:34 -0700 (PDT) X-Received: by 2002:a17:906:5a5c:b0:99b:65fa:e30f with SMTP id my28-20020a1709065a5c00b0099b65fae30fmr2089692ejc.1.1691173474066; Fri, 04 Aug 2023 11:24:34 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id gs2-20020a170906f18200b00992b71d8f19sm1643966ejb.133.2023.08.04.11.24.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:33 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 05/12] drm/nouveau: bo: initialize GEM GPU VA interface Date: Fri, 4 Aug 2023 20:23:45 +0200 Message-ID: <20230804182406.5222-6-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773326686282946269 X-GMAIL-MSGID: 1773326686282946269 Initialize the GEM's DRM GPU VA manager interface in preparation for the (u)vmm implementation, provided by subsequent commits, to make use of it. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7724fe63067d..6130c99b6b2c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -215,6 +215,7 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); if (!nvbo) return ERR_PTR(-ENOMEM); + INIT_LIST_HEAD(&nvbo->head); INIT_LIST_HEAD(&nvbo->entry); INIT_LIST_HEAD(&nvbo->vma_list); @@ -339,6 +340,11 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, dma_resv_init(&nvbo->bo.base._resv); drm_vma_node_reset(&nvbo->bo.base.vma_node); + /* This must be called before ttm_bo_init_reserved(). Subsequent + * bo_move() callbacks might already iterate the GEMs GPUVA list. + */ + drm_gem_gpuva_init(&nvbo->bo.base); + ret = nouveau_bo_init(nvbo, size, align, domain, sg, robj); if (ret) return ret; From patchwork Fri Aug 4 18:23:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131330 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp73599vqr; Fri, 4 Aug 2023 13:06:37 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEGS0DFbNCFeMrO9ucQZ/nmt+1hd4fI+mFNqV1pCf7PpB7dt4G09lir7krXNuXIWQt1EU8p X-Received: by 2002:a2e:7d09:0:b0:2ac:82c1:5a3d with SMTP id y9-20020a2e7d09000000b002ac82c15a3dmr2149142ljc.23.1691179597332; Fri, 04 Aug 2023 13:06:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691179597; cv=none; d=google.com; s=arc-20160816; b=HdqQS89hMJBMMJvNifZ/fq2Ep2KiQp8WP3Eh2/hEdVYYaM0Vd4vdOF3bYStwVu/CQZ JHhkU7d1eScbLx08gR3kSeGE8KvCIBrZFgy5W+kYM+7uqaEUn/l3Qxb9ezd3kVHl27cE SvjX0ZvP1IxOg6QWknv8Uxnof2+Ywr/NzZ95Wic9Q1pcQeSnhGsNy7KtDw+Qbh8oi9LC aHeipTTO5PJVBENn2/jFE1NIKoI/B4bzD5sGlZXs2fHmHhUzXE31MAj5avbtUMglZP98 mt2hKgo7ynGOQx6oFQlCx4gJyfYoyY6OLqYBrny5SdRN4YvsR1/uvbHwjo9pRzzEESZ4 DqPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=sILSYR0gnJ8A9dpqcei0GUdx0191p3j7ECPYiYKPGLY=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=X2/5CkixOJJPdjfuzLzs6QO2cPBPEnflIgayi8K5u7YLcOZTqbCnnetaCIPyM4UQER QYY559JNnUNC56Gf3UW45PcFLCjcNQ41RcaodEjVQBh6Pd7QDatqlt7NGfOhwSKcwevY Wd4blOdlgJJBnWZETVM9+iZAIh+/WftJ8g970bNc+ecY8/djh4FN7/3VTltHEM5+FGwv miVxVOlI2y2g5Pp3S0pWoBkyWhR+Z/zIaO6gNaMm6P71f/hJylmbO0SaMNsBstVj2XVK ThyDPQq67ODkwqy+rJ0gCGNcj6sf+NWygEqEnyEHEN7nsUZ5SHJuT/czkBJxgqUii5Lb FdPA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=EfTrG7fU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bk18-20020a170906b0d200b00997eac101casi1931942ejb.509.2023.08.04.13.06.13; Fri, 04 Aug 2023 13:06:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=EfTrG7fU; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231466AbjHDS0y (ORCPT + 99 others); Fri, 4 Aug 2023 14:26:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53234 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231297AbjHDSZh (ORCPT ); Fri, 4 Aug 2023 14:25:37 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D282A4C31 for ; Fri, 4 Aug 2023 11:24:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173481; 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=sILSYR0gnJ8A9dpqcei0GUdx0191p3j7ECPYiYKPGLY=; b=EfTrG7fUH0Cx+H0Mgx+2C8stlvzpU8awrgnRmY1HUu4dtSuPh4eSLUlqK+E2MYjatZwKc+ tj55+ZwsHkeb/wLofDpJ18kBMS0DcajFoF4Br8my5rf5BA3rG3qRRJYuXG2OkFOdLZQomk FVSksCF/gB/h+rL0ebG+rmlTF81VE4Q= Received: from mail-ed1-f69.google.com (mail-ed1-f69.google.com [209.85.208.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-466-CeNdvE0_PfmMhJq2tLSHwA-1; Fri, 04 Aug 2023 14:24:39 -0400 X-MC-Unique: CeNdvE0_PfmMhJq2tLSHwA-1 Received: by mail-ed1-f69.google.com with SMTP id 4fb4d7f45d1cf-5223d4b9da2so1574406a12.3 for ; Fri, 04 Aug 2023 11:24:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173478; x=1691778278; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sILSYR0gnJ8A9dpqcei0GUdx0191p3j7ECPYiYKPGLY=; b=I4SgxC/F7Owo4xci10aV/6lfTPXKOi3h/FQ4brB8t/kLWJTNo3a/uRKQWqE4QhFXC6 gER3dWBlsH+w37xNBvuUhBO1HOaquwHGaj9YEet8/WUSiKqZ6ZcxSj3ncDttvkBOSpyx 4XD3xVR/tQaZVOkK+MaWxvVl+tK4gB2wat+078j9p7htUfxtgbwIXfHp9z85Hl94ukTf L1rV5jZmZZ9XTulyZHQ5El7PWKMJFoVzrFqhPQNfe1RLQYeHjLMqY1UxJ4afwujodPXs e3IO0LdlrAhXiXt4e6l1KyYj7q69ekeY9h+njObuepwK3V2PII/r92SoBQVQy7qysbqN Exqg== X-Gm-Message-State: AOJu0YyfFx28Z62tvCZO0cGznVY7Qi9zW4XmNwvX/M6pZlCXU+HthiYU VoKsAmsfc0W+dC2RFH4SK23WgVdgtI7wU4xnhH6FJr3mwXLjEALD6qY9+bAPQte29CNVaWpaU2D l46q6t/BUyEmYNMIgp5UqKZm0 X-Received: by 2002:a05:6402:448:b0:51d:d390:143f with SMTP id p8-20020a056402044800b0051dd390143fmr2168716edw.5.1691173478710; Fri, 04 Aug 2023 11:24:38 -0700 (PDT) X-Received: by 2002:a05:6402:448:b0:51d:d390:143f with SMTP id p8-20020a056402044800b0051dd390143fmr2168702edw.5.1691173478516; Fri, 04 Aug 2023 11:24:38 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id r6-20020aa7c146000000b0051e2670d599sm1570383edp.4.2023.08.04.11.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:38 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 06/12] drm/nouveau: move usercopy helpers to nouveau_drv.h Date: Fri, 4 Aug 2023 20:23:46 +0200 Message-ID: <20230804182406.5222-7-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773330337416685072 X-GMAIL-MSGID: 1773330337416685072 Move the usercopy helpers to a common driver header file to make it usable for the new API added in subsequent commits. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_drv.h | 26 ++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_gem.c | 26 -------------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 81350e685b50..d28236021971 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -130,6 +130,32 @@ nouveau_cli(struct drm_file *fpriv) return fpriv ? fpriv->driver_priv : NULL; } +static inline void +u_free(void *addr) +{ + kvfree(addr); +} + +static inline void * +u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) +{ + void *mem; + void __user *userptr = (void __force __user *)(uintptr_t)user; + + size *= nmemb; + + mem = kvmalloc(size, GFP_KERNEL); + if (!mem) + return ERR_PTR(-ENOMEM); + + if (copy_from_user(mem, userptr, size)) { + u_free(mem); + return ERR_PTR(-EFAULT); + } + + return mem; +} + #include #include diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 45ca4eb98f54..a48f42aaeab9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -613,32 +613,6 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, return 0; } -static inline void -u_free(void *addr) -{ - kvfree(addr); -} - -static inline void * -u_memcpya(uint64_t user, unsigned nmemb, unsigned size) -{ - void *mem; - void __user *userptr = (void __force __user *)(uintptr_t)user; - - size *= nmemb; - - mem = kvmalloc(size, GFP_KERNEL); - if (!mem) - return ERR_PTR(-ENOMEM); - - if (copy_from_user(mem, userptr, size)) { - u_free(mem); - return ERR_PTR(-EFAULT); - } - - return mem; -} - static int nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, struct drm_nouveau_gem_pushbuf *req, From patchwork Fri Aug 4 18:23:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131326 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp72865vqr; Fri, 4 Aug 2023 13:05:13 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFi3/hQdsiWavO8nniUSqox216cFbHZpJ/y0DrjxlQlv7SEx2f4xXD9/D0FqBo/+4z944eF X-Received: by 2002:aa7:c64f:0:b0:523:f04:b2d3 with SMTP id z15-20020aa7c64f000000b005230f04b2d3mr2517315edr.11.1691179513584; Fri, 04 Aug 2023 13:05:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691179513; cv=none; d=google.com; s=arc-20160816; b=YAKoWW14swCdTkN31xvBzcj6itNm5ykR3H6FihWuOY0Y3q1YDlAuBRgcckJ7/MSIpw 2V5ZcFk/o75KdzX8aMi3DMEhMZolsI9z+BIuwuYPfMfYpZGFyK/4AjZzMLN2SOYVxUJl lyb9EJAoOw3lecFlQzgomDMzjx9SMZ4f24R7BqxFGrf7GMZxus2+oVcBV2ZD38wYozv+ 5elkQvwVfJNMSRZjUwcM8Ywg5NVoXCRZ/ZJcilUEfc6T0dzvS4Xik6bw9rZRbKaI1lDG R5bkwE2ebj59C+iGfCyYB9CzhmXrmHS9rhfcQG5OnwwooLwGQRnhTH0Dl7gfWxpIbU4F /2Sw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=AdYXUTjXeD+srFScWAxgyp5PN7Frlivhk/MIfK7tk74=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=TkWA/20vAvSfCNZ06zmVcN223qbGOZEiAYPH135DdCAcLmGJDFFaNjhh1s3Cmn2lBV tv3SVviY/AxSHqNxeFSwm/H4++kcJGiWrWTq8CyiVjl0iC4NtoUdqFq5Kq2pcynCdhpR nHElQOjOtCgLSgz1lcC7qOMFHTeVyvPFMSJjrE1xCi5/FftX06fS97gAfDYYJqGod7Rl J69SHniviwtTf9mV8H/8q5Cs2/UkjgiKA2QiVvCvbhwbRae3NhCRmuaWPwLn+mgGFdVP ouV0e9a4Dk/RUhyAVKoojpyFaangc1vp8akXIMGPdo/BSCiYbrv78VyluOcJUdPiJBvS 3egg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=A9HX3Lnh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d4-20020a05640208c400b005231e7a8671si1273717edz.614.2023.08.04.13.04.50; Fri, 04 Aug 2023 13:05:13 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=A9HX3Lnh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231313AbjHDS0o (ORCPT + 99 others); Fri, 4 Aug 2023 14:26:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53186 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231196AbjHDSZh (ORCPT ); Fri, 4 Aug 2023 14:25:37 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 096C24EC1 for ; Fri, 4 Aug 2023 11:24:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173486; 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=AdYXUTjXeD+srFScWAxgyp5PN7Frlivhk/MIfK7tk74=; b=A9HX3LnhJ0q6ksFaGyxUMfONHZNpUgATlP4JI20OcYWaqSDeZJfBCHVpT3y3tDUREJDNWb NV/7VXE/zh//7CLn3tv81k84uEM0RJA9sCSpm7oSTbslhkgFOJmnAh6/aFmA5DKq3duBBT 6BF24jCh2FBLFlWfFcsHT9GCIFfcnzM= Received: from mail-ej1-f70.google.com (mail-ej1-f70.google.com [209.85.218.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-295-m16O31OnPkGJDKcmrcqozg-1; Fri, 04 Aug 2023 14:24:44 -0400 X-MC-Unique: m16O31OnPkGJDKcmrcqozg-1 Received: by mail-ej1-f70.google.com with SMTP id a640c23a62f3a-94f7a2b21fdso164131666b.2 for ; Fri, 04 Aug 2023 11:24:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173484; x=1691778284; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AdYXUTjXeD+srFScWAxgyp5PN7Frlivhk/MIfK7tk74=; b=kVk4fJbqIpsJx8E/XfZ0q9sprtl5fQocqlmdBnEWV76fZ2kQLziGnVzBg/xP2mFdk2 GxzZSlAZsalgIVHOnQeHwH1JiZtHmcb7ymkW+17gRDOGJx1i/PmbdtT5uridA+7pRY8y b5W5iTGDgaRfW99wWtBU3EpQAEpii2XFZ8kYKCUixvf1bMIw4BK65UMGPOmjCAboHUeb rV5VpxqT0H2tuR1cPoaM7Gw3210CtxEW9mclH2U/zIX2b6tSUht6hNHjRNiAM4ppiUTb hRosEgJkNKEJmkHtYdMOsAKBjv5mbe4rEGXq+tf6M5mHvB2efVPG+hz6TS+KC8zZodJC Mxyw== X-Gm-Message-State: AOJu0YzoweZsRC+WSJS9NAIbRRBtXNlfDLlaVK4PAz1WbXx1QGtAzeuQ FTt+63MWYHICv8rhFE1YFFbRqb4Iw7j6/4iMYe+WZqfwW1YiccykUdq+642U7mffd+fFrXpUUq6 W6CJXZTVur3tiA1uo+4XW3LEw X-Received: by 2002:a17:906:10cb:b0:99b:574f:d201 with SMTP id v11-20020a17090610cb00b0099b574fd201mr2292910ejv.40.1691173483734; Fri, 04 Aug 2023 11:24:43 -0700 (PDT) X-Received: by 2002:a17:906:10cb:b0:99b:574f:d201 with SMTP id v11-20020a17090610cb00b0099b574fd201mr2292900ejv.40.1691173483554; Fri, 04 Aug 2023 11:24:43 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id j11-20020a1709062a0b00b0099bd5d28dc4sm1623127eje.195.2023.08.04.11.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:42 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 07/12] drm/nouveau: fence: separate fence alloc and emit Date: Fri, 4 Aug 2023 20:23:47 +0200 Message-ID: <20230804182406.5222-8-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773330249684902448 X-GMAIL-MSGID: 1773330249684902448 The new (VM_BIND) UAPI exports DMA fences through DRM syncobjs. Hence, in order to emit fences within DMA fence signalling critical sections (e.g. as typically done in the DRM GPU schedulers run_job() callback) we need to separate fence allocation and fence emitting. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 9 ++++- drivers/gpu/drm/nouveau/nouveau_bo.c | 52 +++++++++++++++---------- drivers/gpu/drm/nouveau/nouveau_chan.c | 6 ++- drivers/gpu/drm/nouveau/nouveau_dmem.c | 9 +++-- drivers/gpu/drm/nouveau/nouveau_fence.c | 16 +++----- drivers/gpu/drm/nouveau/nouveau_fence.h | 3 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 5 ++- 7 files changed, 59 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index a6f2e681bde9..a34924523133 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1122,11 +1122,18 @@ nv04_page_flip_emit(struct nouveau_channel *chan, PUSH_NVSQ(push, NV_SW, NV_SW_PAGE_FLIP, 0x00000000); PUSH_KICK(push); - ret = nouveau_fence_new(chan, false, pfence); + ret = nouveau_fence_new(pfence); if (ret) goto fail; + ret = nouveau_fence_emit(*pfence, chan); + if (ret) + goto fail_fence_unref; + return 0; + +fail_fence_unref: + nouveau_fence_unref(pfence); fail: spin_lock_irqsave(&dev->event_lock, flags); list_del(&s->head); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 6130c99b6b2c..e38e448d9632 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -823,29 +823,39 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, mutex_lock(&cli->mutex); else mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING); + ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, ctx->interruptible); - if (ret == 0) { - ret = drm->ttm.move(chan, bo, bo->resource, new_reg); - if (ret == 0) { - ret = nouveau_fence_new(chan, false, &fence); - if (ret == 0) { - /* TODO: figure out a better solution here - * - * wait on the fence here explicitly as going through - * ttm_bo_move_accel_cleanup somehow doesn't seem to do it. - * - * Without this the operation can timeout and we'll fallback to a - * software copy, which might take several minutes to finish. - */ - nouveau_fence_wait(fence, false, false); - ret = ttm_bo_move_accel_cleanup(bo, - &fence->base, - evict, false, - new_reg); - nouveau_fence_unref(&fence); - } - } + if (ret) + goto out_unlock; + + ret = drm->ttm.move(chan, bo, bo->resource, new_reg); + if (ret) + goto out_unlock; + + ret = nouveau_fence_new(&fence); + if (ret) + goto out_unlock; + + ret = nouveau_fence_emit(fence, chan); + if (ret) { + nouveau_fence_unref(&fence); + goto out_unlock; } + + /* TODO: figure out a better solution here + * + * wait on the fence here explicitly as going through + * ttm_bo_move_accel_cleanup somehow doesn't seem to do it. + * + * Without this the operation can timeout and we'll fallback to a + * software copy, which might take several minutes to finish. + */ + nouveau_fence_wait(fence, false, false); + ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false, + new_reg); + nouveau_fence_unref(&fence); + +out_unlock: mutex_unlock(&cli->mutex); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 6d639314250a..f69be4c8f9f2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -62,9 +62,11 @@ nouveau_channel_idle(struct nouveau_channel *chan) struct nouveau_fence *fence = NULL; int ret; - ret = nouveau_fence_new(chan, false, &fence); + ret = nouveau_fence_new(&fence); if (!ret) { - ret = nouveau_fence_wait(fence, false, false); + ret = nouveau_fence_emit(fence, chan); + if (!ret) + ret = nouveau_fence_wait(fence, false, false); nouveau_fence_unref(&fence); } diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 789857faa048..4ad40e42cae1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -209,7 +209,8 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf) goto done; } - nouveau_fence_new(dmem->migrate.chan, false, &fence); + if (!nouveau_fence_new(&fence)) + nouveau_fence_emit(fence, dmem->migrate.chan); migrate_vma_pages(&args); nouveau_dmem_fence_done(&fence); dma_unmap_page(drm->dev->dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); @@ -402,7 +403,8 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk) } } - nouveau_fence_new(chunk->drm->dmem->migrate.chan, false, &fence); + if (!nouveau_fence_new(&fence)) + nouveau_fence_emit(fence, chunk->drm->dmem->migrate.chan); migrate_device_pages(src_pfns, dst_pfns, npages); nouveau_dmem_fence_done(&fence); migrate_device_finalize(src_pfns, dst_pfns, npages); @@ -675,7 +677,8 @@ static void nouveau_dmem_migrate_chunk(struct nouveau_drm *drm, addr += PAGE_SIZE; } - nouveau_fence_new(drm->dmem->migrate.chan, false, &fence); + if (!nouveau_fence_new(&fence)) + nouveau_fence_emit(fence, chunk->drm->dmem->migrate.chan); migrate_vma_pages(args); nouveau_dmem_fence_done(&fence); nouveau_pfns_map(svmm, args->vma->vm_mm, args->start, pfns, i); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index ee5e9d40c166..e946408f945b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -210,6 +210,9 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) struct nouveau_fence_priv *priv = (void*)chan->drm->fence; int ret; + if (unlikely(!chan->fence)) + return -ENODEV; + fence->channel = chan; fence->timeout = jiffies + (15 * HZ); @@ -396,25 +399,16 @@ nouveau_fence_unref(struct nouveau_fence **pfence) } int -nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, - struct nouveau_fence **pfence) +nouveau_fence_new(struct nouveau_fence **pfence) { struct nouveau_fence *fence; - int ret = 0; - - if (unlikely(!chan->fence)) - return -ENODEV; fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (!fence) return -ENOMEM; - ret = nouveau_fence_emit(fence, chan); - if (ret) - nouveau_fence_unref(&fence); - *pfence = fence; - return ret; + return 0; } static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 0ca2bc85adf6..7c73c7c9834a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -17,8 +17,7 @@ struct nouveau_fence { unsigned long timeout; }; -int nouveau_fence_new(struct nouveau_channel *, bool sysmem, - struct nouveau_fence **); +int nouveau_fence_new(struct nouveau_fence **); void nouveau_fence_unref(struct nouveau_fence **); int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index a48f42aaeab9..9c8d1b911a01 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -873,8 +873,11 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } } - ret = nouveau_fence_new(chan, false, &fence); + ret = nouveau_fence_new(&fence); + if (!ret) + ret = nouveau_fence_emit(fence, chan); if (ret) { + nouveau_fence_unref(&fence); NV_PRINTK(err, cli, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); goto out; From patchwork Fri Aug 4 18:23:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131346 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp95587vqr; Fri, 4 Aug 2023 13:57:12 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHvm6N1NR88UrlCAypHJMgFgS5iroHl8olntfpm+EaFOpc0WJaZJlv2rlX1K4Z1lKAFaT7B X-Received: by 2002:a05:6a21:999f:b0:137:40ba:d91f with SMTP id ve31-20020a056a21999f00b0013740bad91fmr3937259pzb.10.1691182632492; Fri, 04 Aug 2023 13:57:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691182632; cv=none; d=google.com; s=arc-20160816; b=WmbYcWKciHBbFDRIPE6untwQOlxyOunTYPZSYkIPR+TX3jP4tqqR0DVuc6rDqITQuy Biuzy0eh3Qn41PwH0px2mn/yL4Su91g0oWBYKHtYb6Z3+NZvDa3UqMXlbaRjRYfQpOZG WdjWJIfyOa7vrrDZQ2Yi6CZJwT/krH5iKt3j6c4mBXDJRgVTU7IdAAYDWNLIWr438WU+ bNfxRAq2VVV2L/MRRfs6P3+YFMvpxS+AhK3OhZt5zPPYnvx0ZiXCxkPqPlLbnNyRtzJZ vRdfJgMZPRMzb5y4xfvo/MtzfhjYKEMtC52Hl4KpyaGeWJsn7Ag9SS4j+0s/jxXXWW0v mxsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=GC244PIhZZVEaEMVp/i0uN0Dlx9b0oRSDCpI7qyebQM=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=xlDpXKLeXSWEImQBRRzyB+D/wU+jBd2N6bU0MYRJ7YOeNKRpek87k3hGeiRrp2KdlF syKdOjJfD+bJRmHeXrW9jYsJ4jcGs51Ze77VW1TAzqsliLndH5ue9u1Z9zfZWtYQdN4Q PDlHLgJVgk/AgVZjjkoONnPp2o2ADwny9Jam9tzWKJ3D+k5MyGGMRs6vTqdc+WpqaW3K UdZx7BE54J+8qArb5aLaN4AFfEs9IdEe+x9yL5FrV32jb5gWCCOj1OjM3L+0PVQzYJ+/ xoRZ6o++03CRVlWfZyc8VRDzH/mTizsSjyouky8ANPEpGWVkZNJbKkJvTwgDDGucBK5f SaWA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=WYJ6uujK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i6-20020a655b86000000b00564297a00dfsi2244337pgr.676.2023.08.04.13.56.46; Fri, 04 Aug 2023 13:57:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=WYJ6uujK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229449AbjHDS07 (ORCPT + 99 others); Fri, 4 Aug 2023 14:26:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53414 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231231AbjHDSZj (ORCPT ); Fri, 4 Aug 2023 14:25:39 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 52DD84C05 for ; Fri, 4 Aug 2023 11:24:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173490; 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=GC244PIhZZVEaEMVp/i0uN0Dlx9b0oRSDCpI7qyebQM=; b=WYJ6uujKgJSlNu3ZFnWwL0dkn6Mu1X29VMhOEy5kN+us/TeEth//4c9fc7G2PwtEiqehmx kJuusYmq9iXcFYAhuOHC1Lr/mVopV3oAjrGP7+u1INcc3RNQnygm+uJqe7T6f/8FpxGOjC 85ILiHeecM00X1YdT0Wem/IqOVkFJHY= Received: from mail-ej1-f70.google.com (mail-ej1-f70.google.com [209.85.218.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-465-KHT26yE3PzOC74qHErVe-A-1; Fri, 04 Aug 2023 14:24:49 -0400 X-MC-Unique: KHT26yE3PzOC74qHErVe-A-1 Received: by mail-ej1-f70.google.com with SMTP id a640c23a62f3a-94a356c74e0so150976366b.2 for ; Fri, 04 Aug 2023 11:24:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173488; x=1691778288; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GC244PIhZZVEaEMVp/i0uN0Dlx9b0oRSDCpI7qyebQM=; b=fxm/nR5gdzcu4Ahq9uHko7gTl7+IvotrQDTM0O3U1VOc+sm709n+kqnKjpE7HN0imt c1ncfcEZNTKcMFVUANuy5X2VHLJBr/VNRb5waHpGnLahTzJO5JdAi0ipa3olhhjr2QD7 JnaUG6ixuH/umShsgv6nwAWEq4RJxIcwVFZ58g2lUoZIFbaF3nYr3RRoJC3sr4vh70D9 D8AVmjvZWIRwucmagizYIjvK8sSvcs7biEGvBwpqTnj5ga0BpACYvyQQz3miIGUjOVkp rW2kp+JNOwyO0Z1QNE/cmtdjvssyasUEDDDyhvz263LvZ/d2KwP6Z8Qj8BbxZKpDiEQP ZHsw== X-Gm-Message-State: AOJu0YzgZbk9OBFVNrRbNoamdGizB1qizD0Y0YM6gIRC3G9VIhdwAj+a xZLikzZ2YjgHCwW3Bomcii78KdwOIQatLKsA0RUHJnEjTqouEYiEt87/uMXKwv2bx5EcUjlo2rx lu29Kn2oN6OhaqZJjgLHtmIyH X-Received: by 2002:a17:906:31cd:b0:994:2fa9:7446 with SMTP id f13-20020a17090631cd00b009942fa97446mr1890096ejf.46.1691173488304; Fri, 04 Aug 2023 11:24:48 -0700 (PDT) X-Received: by 2002:a17:906:31cd:b0:994:2fa9:7446 with SMTP id f13-20020a17090631cd00b009942fa97446mr1890079ejf.46.1691173487983; Fri, 04 Aug 2023 11:24:47 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id bw4-20020a170906c1c400b009829d2e892csm1674052ejb.15.2023.08.04.11.24.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:47 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 08/12] drm/nouveau: fence: fail to emit when fence context is killed Date: Fri, 4 Aug 2023 20:23:48 +0200 Message-ID: <20230804182406.5222-9-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773333520417411596 X-GMAIL-MSGID: 1773333520417411596 The new VM_BIND UAPI implementation introduced in subsequent commits will allow asynchronous jobs processing push buffers and emitting fences. If a fence context is killed, e.g. due to a channel fault, jobs which are already queued for execution might still emit new fences. In such a case a job would hang forever. To fix that, fail to emit a new fence on a killed fence context with -ENODEV to unblock the job. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_fence.c | 7 +++++++ drivers/gpu/drm/nouveau/nouveau_fence.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index e946408f945b..77c739a55b19 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -96,6 +96,7 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) if (nouveau_fence_signal(fence)) nvif_event_block(&fctx->event); } + fctx->killed = 1; spin_unlock_irqrestore(&fctx->lock, flags); } @@ -229,6 +230,12 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) dma_fence_get(&fence->base); spin_lock_irq(&fctx->lock); + if (unlikely(fctx->killed)) { + spin_unlock_irq(&fctx->lock); + dma_fence_put(&fence->base); + return -ENODEV; + } + if (nouveau_fence_update(chan, fctx)) nvif_event_block(&fctx->event); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 7c73c7c9834a..2c72d96ef17d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -44,7 +44,7 @@ struct nouveau_fence_chan { char name[32]; struct nvif_event event; - int notify_ref, dead; + int notify_ref, dead, killed; }; struct nouveau_fence_priv { From patchwork Fri Aug 4 18:23:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131315 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp49717vqr; Fri, 4 Aug 2023 12:16:59 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGJFE9D+JrOc5O73zIRPxILigWDdf1TjkuuH3qULFhMv6j3o2KTty8HXEibIK9rLIBYMGdw X-Received: by 2002:a17:902:d486:b0:1b8:3936:7b64 with SMTP id c6-20020a170902d48600b001b839367b64mr720467plg.1.1691176619014; Fri, 04 Aug 2023 12:16:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691176619; cv=none; d=google.com; s=arc-20160816; b=et4ef9pgaVpDdR2mdM15neUIIZSHTLoerzJvZjf4Y9+CG09dB7jTMksFGeLJo/B70i hE27peAzemHBfSt+TsQSxa5DncHqUt8fUkJ4pt43tXA7yNdgJZipo6O9qiXZOHOB5Tsb INb+Adysm25ia7gaKeunMqI4cfgZFu6EaMr/UUMYX/fFcRNUM7/ME+w8BBgPGeBUKMkG h4zSeEq4P1GPqmczqEyxtAq7TzOnxVqoaIw/zdnqmcgjHZgVtcx/KlFM4IxUINKhEceY FwaYa9v/JN93sjyYgsa35UVQdHrK7Sc4Lnvs8+Xk3QLzbhZ1hfbGna4v762RtvAPz5yV +ZuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=FPFh5xK9R3PMhoxLIZOGRTrlUVBMred7+qWqFlBzAlw=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=hQ9cB3Y5w2JXFKrrqPJYh+oIlWpG5xVJbMlOdsyKw42GvWmWtkrDaLwTBT8w4ViCkG nTb8wns13VVLpd0KIMNiwB7HrkkoWUaUbcsnsu9fnl7NxQEq9fg2HJkrsDq1mJhUxi9Z JD7f9nXftsjT4cScQrmydtO7LXcXaRvr4kX6XgCCC6e54GifVTcKYLBsmCAmb3p7AWM/ Dx+ohErASAA9pCZ7xY/wqRSi4oXEYBBkL/6Hruzjs5D9UX9GtvG4qnSe686kJJrSBR5G czMzrpDpahnDejp7J/EclPGIIkd9TXMZR3RxYT6+w6w9wB9xzZueixQbfrDfHUoMX1f/ +rGw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d9-20020a170902654900b001b54bdd6412si2180972pln.396.2023.08.04.12.16.46; Fri, 04 Aug 2023 12:16:58 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 S231557AbjHDS1T (ORCPT + 99 others); Fri, 4 Aug 2023 14:27:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53506 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230466AbjHDS0I (ORCPT ); Fri, 4 Aug 2023 14:26:08 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D4B714ED6 for ; Fri, 4 Aug 2023 11:25:03 -0700 (PDT) Received: from mail-ed1-f70.google.com (mail-ed1-f70.google.com [209.85.208.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-327-XzlRVz4iOpGxNCRi1Vgz9w-1; Fri, 04 Aug 2023 14:24:56 -0400 X-MC-Unique: XzlRVz4iOpGxNCRi1Vgz9w-1 Received: by mail-ed1-f70.google.com with SMTP id 4fb4d7f45d1cf-521a38098faso1575040a12.2 for ; Fri, 04 Aug 2023 11:24:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173493; x=1691778293; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FPFh5xK9R3PMhoxLIZOGRTrlUVBMred7+qWqFlBzAlw=; b=OIZlow0dVA+2ddyYRkRqG1/rfbhbisJ7xboYp838wyNCTnCAWXgHAek2AaA+APNH4t ooqGb461NT00TqeCYGpvqdEVKFVxhwrkExCxfc9sEZQ0VPfscvoN04R69cpfrr7ql7xx BzdymAeikXKkEoyhK3Xx16Pu+oFLsWXgjAfshnYAsm5z5FcUDY/8zXRBYHZ94WDaReaW GO32cvIBma2fdIhTIT+SgQZehFqqF3WPX5EEkok+QE3hs4uWZkK4ivas5HjkdsfG00Gp Ze/VJZLtgHZ0M00IBA6M2nGwQyiTv8CAnFqpGmnwiTaGuvmvoELRwDByGhjUkBUYzJUW F3+w== X-Gm-Message-State: AOJu0YyA/b/tcqMryH619iI6rnG17JyWTKw3Dtfj8/9Q882woEvhsMzR yHBZXTWTTotn7lkP16J4gzfLYV+kqn5HGL6yonqT1bZP7FjV22KX4FBaIgwzP9STpZweN/+Duny 9zlTmFj9fiF3N17L4eoaPBNBO X-Received: by 2002:a05:6402:d7:b0:523:1e18:3a78 with SMTP id i23-20020a05640200d700b005231e183a78mr1852253edu.12.1691173492888; Fri, 04 Aug 2023 11:24:52 -0700 (PDT) X-Received: by 2002:a05:6402:d7:b0:523:1e18:3a78 with SMTP id i23-20020a05640200d700b005231e183a78mr1852238edu.12.1691173492693; Fri, 04 Aug 2023 11:24:52 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id w16-20020a50fa90000000b00522295516c4sm1551054edr.90.2023.08.04.11.24.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:52 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 09/12] drm/nouveau: chan: provide nouveau_channel_kill() Date: Fri, 4 Aug 2023 20:23:49 +0200 Message-ID: <20230804182406.5222-10-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773327214334789355 X-GMAIL-MSGID: 1773327214334789355 The new VM_BIND UAPI implementation introduced in subsequent commits will allow asynchronous jobs processing push buffers and emitting fences. If a job times out, we need a way to recover from this situation. For now, simply kill the channel to unblock all hung up jobs and signal userspace that the device is dead on the next EXEC or VM_BIND ioctl. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_chan.c | 14 +++++++++++--- drivers/gpu/drm/nouveau/nouveau_chan.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index f69be4c8f9f2..1fd5ccf41128 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -40,6 +40,14 @@ MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM"); int nouveau_vram_pushbuf; module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); +void +nouveau_channel_kill(struct nouveau_channel *chan) +{ + atomic_set(&chan->killed, 1); + if (chan->fence) + nouveau_fence_context_kill(chan->fence, -ENODEV); +} + static int nouveau_channel_killed(struct nvif_event *event, void *repv, u32 repc) { @@ -47,9 +55,9 @@ nouveau_channel_killed(struct nvif_event *event, void *repv, u32 repc) struct nouveau_cli *cli = (void *)chan->user.client; NV_PRINTK(warn, cli, "channel %d killed!\n", chan->chid); - atomic_set(&chan->killed, 1); - if (chan->fence) - nouveau_fence_context_kill(chan->fence, -ENODEV); + + if (unlikely(!atomic_read(&chan->killed))) + nouveau_channel_kill(chan); return NVIF_EVENT_DROP; } diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index bad7466bd0d5..5de2ef4e98c2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -66,6 +66,7 @@ int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, bool priv, u32 vram, u32 gart, struct nouveau_channel **); void nouveau_channel_del(struct nouveau_channel **); int nouveau_channel_idle(struct nouveau_channel *); +void nouveau_channel_kill(struct nouveau_channel *); extern int nouveau_vram_pushbuf; From patchwork Fri Aug 4 18:23:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131304 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp41767vqr; Fri, 4 Aug 2023 12:03:33 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFIsnzlsYM1IKia97eugScwHYnoYQ1YMEVH0pNzi8AcuweKDDYlHfYF/l7Gm83jpSEfx6MA X-Received: by 2002:a05:6512:20d3:b0:4f8:6a29:b59b with SMTP id u19-20020a05651220d300b004f86a29b59bmr1760799lfr.64.1691175813583; Fri, 04 Aug 2023 12:03:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691175813; cv=none; d=google.com; s=arc-20160816; b=HWXDHkLuCoZd4VNWT4xzzq2bwiWBnXSOutqfluFiAOeo+4+Jupfz4jLNr3n/8Fvdv0 B2JrVuvynIiehnuu3R5kR8VLBDVMvYchKWiXeTjunk8rNF5N8j9Z95dQ70dMnRMOc8WN G6/mQN9bukBm2DUWT9g7sy3DDvTdxDTmOkL2D60cD6qhr6vAMx94/Et4EsjeFYE9PlxC tW122XNruexJBi+vI6/h7dI0G3yf9Nh1RlY3PaWHHVzbqbRopPd/ebhKYaG7jekJKTOk uS0b1BPD69iC3HvdapUFe5jhmmElpuVL9tAe7mQpLF5RZbXIPy67xDdxsuoJoP8xKP06 OopA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=uv2HeJajlPU2lOXFcrW96Xg4X49DXjWoqR/YgwpDjYQ=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=QMGCUftnNNMXY3jN5LmDlZ66tLZo/aGM39+JP62iBYPiqQfZWx98nZpsqF7cBKjAPv 4zhObVG2omrQ2vGGgwSpWuzmY5TnzvoFvyH7SOs1jX+H/9oFY8h2KQ0Ou1w5HSXHVNNP HoR+aq7avXkaX0hNba5c5+ROfGFPZLU+Uu2LoWl7cK7RrBeXwy2q8WE3FjL1eWqySeNL bhqB/HuLzopQYnHxN6WqmlFGQOu4vuhiuiCuGp+e11cyIGIdI5xGfHBTIPCt4FUvzm1B czuHkRfCMVFwJvH008KJn4CH02xlEyjMSSMBQ/L9z/a5X69Xj5zeQVOoYUUdoLOo9ng1 sliA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=AkgES0qJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id c3-20020a170906170300b0099bca8453f0si1978170eje.764.2023.08.04.12.02.58; Fri, 04 Aug 2023 12:03:33 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=AkgES0qJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231486AbjHDS1O (ORCPT + 99 others); Fri, 4 Aug 2023 14:27:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53724 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230338AbjHDS0C (ORCPT ); Fri, 4 Aug 2023 14:26:02 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 839FB4ECD for ; Fri, 4 Aug 2023 11:25:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173501; 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=uv2HeJajlPU2lOXFcrW96Xg4X49DXjWoqR/YgwpDjYQ=; b=AkgES0qJZnHdJ9yDuW/1AvMD73Gt1OjRFTrY4FGfYCjOzje5Wn47xyfiKa8ZvO5/HlQ1qv F8+VOSvym/LShwMJ2WFqRlE2t/4J/AafHGZvGQ+i/CVrUZwuPHRXVUNGd7ZLeeaS9jFhfl UqvCyPe1PdxnvMFHLkrmFhKIDUKumpI= Received: from mail-lf1-f69.google.com (mail-lf1-f69.google.com [209.85.167.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-132-QSwPMF17Mv2rUTSOq3rdjQ-1; Fri, 04 Aug 2023 14:24:59 -0400 X-MC-Unique: QSwPMF17Mv2rUTSOq3rdjQ-1 Received: by mail-lf1-f69.google.com with SMTP id 2adb3069b0e04-4fe157ebea0so2384956e87.1 for ; Fri, 04 Aug 2023 11:24:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173498; x=1691778298; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uv2HeJajlPU2lOXFcrW96Xg4X49DXjWoqR/YgwpDjYQ=; b=UJw0hZH2SrWDmdauq5pURO/cuw5+bRlxYXAWJVdF1V8mNsDJKRC5EEr7Zb//alOJ9c jAQW8RT4ZnIeI2fKpcYF5B+9VrlTYXuwVP95RgQFdYcguE9iicZ0EXoHO/zu+wQo6GPW fbI6kAf/9ANuVyjiBW/T/1p1CaxsK7MkvEkd3o8S7V96kUEXk935rMNGTaj8ADBVJb52 g7HfggTu6YNrV/jTX207vVaBizB2RxUsrRrCpR1eR0bzAoYSLZpy45ONY63sG579PuHE C4jzfprSQjM07TtLAgJqnSjX7l/oa/QPhcUj3LGp9P99qyKlVoU3XoaZgT80BesTYmIr EzEA== X-Gm-Message-State: AOJu0YywT6F5VjD0dM0Y4q0L33vsDoo+jbQiVDUMu2EgzFMM1ehshdZH EGRygeQvnj70HKMmmtQVeqgLj5l36uoG+s3QdpWeXuZemlMx0V1CQe/uLE3Yae7aIy3mldGRZjY dFQ7tUNgnwAyi2Hfnvr0hzyBm X-Received: by 2002:a05:6512:104e:b0:4fd:cae7:2393 with SMTP id c14-20020a056512104e00b004fdcae72393mr2147688lfb.2.1691173498042; Fri, 04 Aug 2023 11:24:58 -0700 (PDT) X-Received: by 2002:a05:6512:104e:b0:4fd:cae7:2393 with SMTP id c14-20020a056512104e00b004fdcae72393mr2147660lfb.2.1691173497553; Fri, 04 Aug 2023 11:24:57 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id z23-20020a170906435700b00997d7aa59fasm1660250ejm.14.2023.08.04.11.24.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:24:56 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 10/12] drm/nouveau: nvkm/vmm: implement raw ops to manage uvmm Date: Fri, 4 Aug 2023 20:23:50 +0200 Message-ID: <20230804182406.5222-11-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773326369675185021 X-GMAIL-MSGID: 1773326369675185021 The new VM_BIND UAPI uses the DRM GPU VA manager to manage the VA space. Hence, we a need a way to manipulate the MMUs page tables without going through the internal range allocator implemented by nvkm/vmm. This patch adds a raw interface for nvkm/vmm to pass the resposibility for managing the address space and the corresponding map/unmap/sparse operations to the upper layers. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/include/nvif/if000c.h | 26 ++- drivers/gpu/drm/nouveau/include/nvif/vmm.h | 19 +- .../gpu/drm/nouveau/include/nvkm/subdev/mmu.h | 20 +- drivers/gpu/drm/nouveau/nouveau_svm.c | 2 +- drivers/gpu/drm/nouveau/nouveau_vmm.c | 4 +- drivers/gpu/drm/nouveau/nvif/vmm.c | 100 +++++++- .../gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c | 213 ++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 197 ++++++++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h | 25 ++ .../drm/nouveau/nvkm/subdev/mmu/vmmgf100.c | 16 +- .../drm/nouveau/nvkm/subdev/mmu/vmmgp100.c | 16 +- .../gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c | 27 ++- 12 files changed, 566 insertions(+), 99 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000c.h b/drivers/gpu/drm/nouveau/include/nvif/if000c.h index 9c7ff56831c5..a5a182b3c28d 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if000c.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if000c.h @@ -3,7 +3,10 @@ struct nvif_vmm_v0 { __u8 version; __u8 page_nr; - __u8 managed; +#define NVIF_VMM_V0_TYPE_UNMANAGED 0x00 +#define NVIF_VMM_V0_TYPE_MANAGED 0x01 +#define NVIF_VMM_V0_TYPE_RAW 0x02 + __u8 type; __u8 pad03[5]; __u64 addr; __u64 size; @@ -17,6 +20,7 @@ struct nvif_vmm_v0 { #define NVIF_VMM_V0_UNMAP 0x04 #define NVIF_VMM_V0_PFNMAP 0x05 #define NVIF_VMM_V0_PFNCLR 0x06 +#define NVIF_VMM_V0_RAW 0x07 #define NVIF_VMM_V0_MTHD(i) ((i) + 0x80) struct nvif_vmm_page_v0 { @@ -66,6 +70,26 @@ struct nvif_vmm_unmap_v0 { __u64 addr; }; +struct nvif_vmm_raw_v0 { + __u8 version; +#define NVIF_VMM_RAW_V0_GET 0x0 +#define NVIF_VMM_RAW_V0_PUT 0x1 +#define NVIF_VMM_RAW_V0_MAP 0x2 +#define NVIF_VMM_RAW_V0_UNMAP 0x3 +#define NVIF_VMM_RAW_V0_SPARSE 0x4 + __u8 op; + __u8 sparse; + __u8 ref; + __u8 shift; + __u32 argc; + __u8 pad01[7]; + __u64 addr; + __u64 size; + __u64 offset; + __u64 memory; + __u64 argv; +}; + struct nvif_vmm_pfnmap_v0 { __u8 version; __u8 page; diff --git a/drivers/gpu/drm/nouveau/include/nvif/vmm.h b/drivers/gpu/drm/nouveau/include/nvif/vmm.h index a2ee92201ace..0ecedd0ee0a5 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/vmm.h +++ b/drivers/gpu/drm/nouveau/include/nvif/vmm.h @@ -4,6 +4,12 @@ struct nvif_mem; struct nvif_mmu; +enum nvif_vmm_type { + UNMANAGED, + MANAGED, + RAW, +}; + enum nvif_vmm_get { ADDR, PTES, @@ -30,8 +36,9 @@ struct nvif_vmm { int page_nr; }; -int nvif_vmm_ctor(struct nvif_mmu *, const char *name, s32 oclass, bool managed, - u64 addr, u64 size, void *argv, u32 argc, struct nvif_vmm *); +int nvif_vmm_ctor(struct nvif_mmu *, const char *name, s32 oclass, + enum nvif_vmm_type, u64 addr, u64 size, void *argv, u32 argc, + struct nvif_vmm *); void nvif_vmm_dtor(struct nvif_vmm *); int nvif_vmm_get(struct nvif_vmm *, enum nvif_vmm_get, bool sparse, u8 page, u8 align, u64 size, struct nvif_vma *); @@ -39,4 +46,12 @@ void nvif_vmm_put(struct nvif_vmm *, struct nvif_vma *); int nvif_vmm_map(struct nvif_vmm *, u64 addr, u64 size, void *argv, u32 argc, struct nvif_mem *, u64 offset); int nvif_vmm_unmap(struct nvif_vmm *, u64); + +int nvif_vmm_raw_get(struct nvif_vmm *vmm, u64 addr, u64 size, u8 shift); +int nvif_vmm_raw_put(struct nvif_vmm *vmm, u64 addr, u64 size, u8 shift); +int nvif_vmm_raw_map(struct nvif_vmm *vmm, u64 addr, u64 size, u8 shift, + void *argv, u32 argc, struct nvif_mem *mem, u64 offset); +int nvif_vmm_raw_unmap(struct nvif_vmm *vmm, u64 addr, u64 size, + u8 shift, bool sparse); +int nvif_vmm_raw_sparse(struct nvif_vmm *vmm, u64 addr, u64 size, bool ref); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h index 70e7887ef4b4..2fd2f2433fc7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h @@ -17,6 +17,7 @@ struct nvkm_vma { bool part:1; /* Region was split from an allocated region by map(). */ bool busy:1; /* Region busy (for temporarily preventing user access). */ bool mapped:1; /* Region contains valid pages. */ + bool no_comp:1; /* Force no memory compression. */ struct nvkm_memory *memory; /* Memory currently mapped into VMA. */ struct nvkm_tags *tags; /* Compression tag reference. */ }; @@ -27,10 +28,26 @@ struct nvkm_vmm { const char *name; u32 debug; struct kref kref; - struct mutex mutex; + + struct { + struct mutex vmm; + struct mutex ref; + struct mutex map; + } mutex; u64 start; u64 limit; + struct { + struct { + u64 addr; + u64 size; + } p; + struct { + u64 addr; + u64 size; + } n; + bool raw; + } managed; struct nvkm_vmm_pt *pd; struct list_head join; @@ -70,6 +87,7 @@ struct nvkm_vmm_map { const struct nvkm_vmm_page *page; + bool no_comp; struct nvkm_tags *tags; u64 next; u64 type; diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c index a74ba8d84ba7..186351ecf72f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -350,7 +350,7 @@ nouveau_svmm_init(struct drm_device *dev, void *data, * VMM instead of the standard one. */ ret = nvif_vmm_ctor(&cli->mmu, "svmVmm", - cli->vmm.vmm.object.oclass, true, + cli->vmm.vmm.object.oclass, MANAGED, args->unmanaged_addr, args->unmanaged_size, &(struct gp100_vmm_v0) { .fault_replay = true, diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.c b/drivers/gpu/drm/nouveau/nouveau_vmm.c index 67d6619fcd5e..a6602c012671 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vmm.c @@ -128,8 +128,8 @@ nouveau_vmm_fini(struct nouveau_vmm *vmm) int nouveau_vmm_init(struct nouveau_cli *cli, s32 oclass, struct nouveau_vmm *vmm) { - int ret = nvif_vmm_ctor(&cli->mmu, "drmVmm", oclass, false, PAGE_SIZE, - 0, NULL, 0, &vmm->vmm); + int ret = nvif_vmm_ctor(&cli->mmu, "drmVmm", oclass, UNMANAGED, + PAGE_SIZE, 0, NULL, 0, &vmm->vmm); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvif/vmm.c b/drivers/gpu/drm/nouveau/nvif/vmm.c index 6053d6dc2184..99296f03371a 100644 --- a/drivers/gpu/drm/nouveau/nvif/vmm.c +++ b/drivers/gpu/drm/nouveau/nvif/vmm.c @@ -104,6 +104,90 @@ nvif_vmm_get(struct nvif_vmm *vmm, enum nvif_vmm_get type, bool sparse, return ret; } +int +nvif_vmm_raw_get(struct nvif_vmm *vmm, u64 addr, u64 size, + u8 shift) +{ + struct nvif_vmm_raw_v0 args = { + .version = 0, + .op = NVIF_VMM_RAW_V0_GET, + .addr = addr, + .size = size, + .shift = shift, + }; + + return nvif_object_mthd(&vmm->object, NVIF_VMM_V0_RAW, + &args, sizeof(args)); +} + +int +nvif_vmm_raw_put(struct nvif_vmm *vmm, u64 addr, u64 size, u8 shift) +{ + struct nvif_vmm_raw_v0 args = { + .version = 0, + .op = NVIF_VMM_RAW_V0_PUT, + .addr = addr, + .size = size, + .shift = shift, + }; + + return nvif_object_mthd(&vmm->object, NVIF_VMM_V0_RAW, + &args, sizeof(args)); +} + +int +nvif_vmm_raw_map(struct nvif_vmm *vmm, u64 addr, u64 size, u8 shift, + void *argv, u32 argc, struct nvif_mem *mem, u64 offset) +{ + struct nvif_vmm_raw_v0 args = { + .version = 0, + .op = NVIF_VMM_RAW_V0_MAP, + .addr = addr, + .size = size, + .shift = shift, + .memory = nvif_handle(&mem->object), + .offset = offset, + .argv = (u64)(uintptr_t)argv, + .argc = argc, + }; + + + return nvif_object_mthd(&vmm->object, NVIF_VMM_V0_RAW, + &args, sizeof(args)); +} + +int +nvif_vmm_raw_unmap(struct nvif_vmm *vmm, u64 addr, u64 size, + u8 shift, bool sparse) +{ + struct nvif_vmm_raw_v0 args = { + .version = 0, + .op = NVIF_VMM_RAW_V0_UNMAP, + .addr = addr, + .size = size, + .shift = shift, + .sparse = sparse, + }; + + return nvif_object_mthd(&vmm->object, NVIF_VMM_V0_RAW, + &args, sizeof(args)); +} + +int +nvif_vmm_raw_sparse(struct nvif_vmm *vmm, u64 addr, u64 size, bool ref) +{ + struct nvif_vmm_raw_v0 args = { + .version = 0, + .op = NVIF_VMM_RAW_V0_SPARSE, + .addr = addr, + .size = size, + .ref = ref, + }; + + return nvif_object_mthd(&vmm->object, NVIF_VMM_V0_RAW, + &args, sizeof(args)); +} + void nvif_vmm_dtor(struct nvif_vmm *vmm) { @@ -112,8 +196,9 @@ nvif_vmm_dtor(struct nvif_vmm *vmm) } int -nvif_vmm_ctor(struct nvif_mmu *mmu, const char *name, s32 oclass, bool managed, - u64 addr, u64 size, void *argv, u32 argc, struct nvif_vmm *vmm) +nvif_vmm_ctor(struct nvif_mmu *mmu, const char *name, s32 oclass, + enum nvif_vmm_type type, u64 addr, u64 size, void *argv, u32 argc, + struct nvif_vmm *vmm) { struct nvif_vmm_v0 *args; u32 argn = sizeof(*args) + argc; @@ -125,9 +210,18 @@ nvif_vmm_ctor(struct nvif_mmu *mmu, const char *name, s32 oclass, bool managed, if (!(args = kmalloc(argn, GFP_KERNEL))) return -ENOMEM; args->version = 0; - args->managed = managed; args->addr = addr; args->size = size; + + switch (type) { + case UNMANAGED: args->type = NVIF_VMM_V0_TYPE_UNMANAGED; break; + case MANAGED: args->type = NVIF_VMM_V0_TYPE_MANAGED; break; + case RAW: args->type = NVIF_VMM_V0_TYPE_RAW; break; + default: + WARN_ON(1); + return -EINVAL; + } + memcpy(args->data, argv, argc); ret = nvif_object_ctor(&mmu->object, name ? name : "nvifVmm", 0, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c index 524cd3c0e3fe..38b7ced934b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c @@ -58,10 +58,13 @@ nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; + if (nvkm_vmm_in_managed_range(vmm, addr, size) && vmm->managed.raw) + return -EINVAL; + if (size) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_pfn_unmap(vmm, addr, size); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } return ret; @@ -88,10 +91,13 @@ nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; + if (nvkm_vmm_in_managed_range(vmm, addr, size) && vmm->managed.raw) + return -EINVAL; + if (size) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_pfn_map(vmm, page, addr, size, phys); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } return ret; @@ -113,7 +119,10 @@ nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; - mutex_lock(&vmm->mutex); + if (nvkm_vmm_in_managed_range(vmm, addr, 0) && vmm->managed.raw) + return -EINVAL; + + mutex_lock(&vmm->mutex.vmm); vma = nvkm_vmm_node_search(vmm, addr); if (ret = -ENOENT, !vma || vma->addr != addr) { VMM_DEBUG(vmm, "lookup %016llx: %016llx", @@ -134,7 +143,7 @@ nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) nvkm_vmm_unmap_locked(vmm, vma, false); ret = 0; done: - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); return ret; } @@ -159,13 +168,16 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; + if (nvkm_vmm_in_managed_range(vmm, addr, size) && vmm->managed.raw) + return -EINVAL; + memory = nvkm_umem_search(client, handle); if (IS_ERR(memory)) { VMM_DEBUG(vmm, "memory %016llx %ld\n", handle, PTR_ERR(memory)); return PTR_ERR(memory); } - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); if (ret = -ENOENT, !(vma = nvkm_vmm_node_search(vmm, addr))) { VMM_DEBUG(vmm, "lookup %016llx", addr); goto fail; @@ -198,7 +210,7 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } } vma->busy = true; - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); ret = nvkm_memory_map(memory, offset, vmm, vma, argv, argc); if (ret == 0) { @@ -207,11 +219,11 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) return 0; } - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); vma->busy = false; nvkm_vmm_unmap_region(vmm, vma); fail: - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); nvkm_memory_unref(&memory); return ret; } @@ -232,7 +244,7 @@ nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); vma = nvkm_vmm_node_search(vmm, args->v0.addr); if (ret = -ENOENT, !vma || vma->addr != addr || vma->part) { VMM_DEBUG(vmm, "lookup %016llx: %016llx %d", addr, @@ -248,7 +260,7 @@ nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc) nvkm_vmm_put_locked(vmm, vma); ret = 0; done: - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); return ret; } @@ -275,10 +287,10 @@ nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_get_locked(vmm, getref, mapref, sparse, page, align, size, &vma); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); if (ret) return ret; @@ -314,6 +326,167 @@ nvkm_uvmm_mthd_page(struct nvkm_uvmm *uvmm, void *argv, u32 argc) return 0; } +static inline int +nvkm_uvmm_page_index(struct nvkm_uvmm *uvmm, u64 size, u8 shift, u8 *refd) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + const struct nvkm_vmm_page *page; + + if (likely(shift)) { + for (page = vmm->func->page; page->shift; page++) { + if (shift == page->shift) + break; + } + + if (!page->shift || !IS_ALIGNED(size, 1ULL << page->shift)) { + VMM_DEBUG(vmm, "page %d %016llx", shift, size); + return -EINVAL; + } + } else { + return -EINVAL; + } + *refd = page - vmm->func->page; + + return 0; +} + +static int +nvkm_uvmm_mthd_raw_get(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + return nvkm_vmm_raw_get(vmm, args->addr, args->size, refd); +} + +static int +nvkm_uvmm_mthd_raw_put(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + nvkm_vmm_raw_put(vmm, args->addr, args->size, refd); + + return 0; +} + +static int +nvkm_uvmm_mthd_raw_map(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_client *client = uvmm->object.client; + struct nvkm_vmm *vmm = uvmm->vmm; + struct nvkm_vma vma = { + .addr = args->addr, + .size = args->size, + .used = true, + .mapref = false, + .no_comp = true, + }; + struct nvkm_memory *memory; + u64 handle = args->memory; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + vma.page = vma.refd = refd; + + memory = nvkm_umem_search(client, args->memory); + if (IS_ERR(memory)) { + VMM_DEBUG(vmm, "memory %016llx %ld\n", handle, PTR_ERR(memory)); + return PTR_ERR(memory); + } + + ret = nvkm_memory_map(memory, args->offset, vmm, &vma, + (void *)args->argv, args->argc); + + nvkm_memory_unref(&vma.memory); + nvkm_memory_unref(&memory); + return ret; +} + +static int +nvkm_uvmm_mthd_raw_unmap(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + u8 refd; + int ret; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + ret = nvkm_uvmm_page_index(uvmm, args->size, args->shift, &refd); + if (ret) + return ret; + + nvkm_vmm_raw_unmap(vmm, args->addr, args->size, + args->sparse, refd); + + return 0; +} + +static int +nvkm_uvmm_mthd_raw_sparse(struct nvkm_uvmm *uvmm, struct nvif_vmm_raw_v0 *args) +{ + struct nvkm_vmm *vmm = uvmm->vmm; + + if (!nvkm_vmm_in_managed_range(vmm, args->addr, args->size)) + return -EINVAL; + + return nvkm_vmm_raw_sparse(vmm, args->addr, args->size, args->ref); +} + +static int +nvkm_uvmm_mthd_raw(struct nvkm_uvmm *uvmm, void *argv, u32 argc) +{ + union { + struct nvif_vmm_raw_v0 v0; + } *args = argv; + int ret = -ENOSYS; + + if (!uvmm->vmm->managed.raw) + return -EINVAL; + + if ((ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) + return ret; + + switch (args->v0.op) { + case NVIF_VMM_RAW_V0_GET: + return nvkm_uvmm_mthd_raw_get(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_PUT: + return nvkm_uvmm_mthd_raw_put(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_MAP: + return nvkm_uvmm_mthd_raw_map(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_UNMAP: + return nvkm_uvmm_mthd_raw_unmap(uvmm, &args->v0); + case NVIF_VMM_RAW_V0_SPARSE: + return nvkm_uvmm_mthd_raw_sparse(uvmm, &args->v0); + default: + return -EINVAL; + }; +} + static int nvkm_uvmm_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) { @@ -326,6 +499,7 @@ nvkm_uvmm_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) case NVIF_VMM_V0_UNMAP : return nvkm_uvmm_mthd_unmap (uvmm, argv, argc); case NVIF_VMM_V0_PFNMAP: return nvkm_uvmm_mthd_pfnmap(uvmm, argv, argc); case NVIF_VMM_V0_PFNCLR: return nvkm_uvmm_mthd_pfnclr(uvmm, argv, argc); + case NVIF_VMM_V0_RAW : return nvkm_uvmm_mthd_raw (uvmm, argv, argc); case NVIF_VMM_V0_MTHD(0x00) ... NVIF_VMM_V0_MTHD(0x7f): if (uvmm->vmm->func->mthd) { return uvmm->vmm->func->mthd(uvmm->vmm, @@ -366,10 +540,11 @@ nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_uvmm *uvmm; int ret = -ENOSYS; u64 addr, size; - bool managed; + bool managed, raw; if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, more))) { - managed = args->v0.managed != 0; + managed = args->v0.type == NVIF_VMM_V0_TYPE_MANAGED; + raw = args->v0.type == NVIF_VMM_V0_TYPE_RAW; addr = args->v0.addr; size = args->v0.size; } else @@ -377,12 +552,13 @@ nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, if (!(uvmm = kzalloc(sizeof(*uvmm), GFP_KERNEL))) return -ENOMEM; + nvkm_object_ctor(&nvkm_uvmm, oclass, &uvmm->object); *pobject = &uvmm->object; if (!mmu->vmm) { - ret = mmu->func->vmm.ctor(mmu, managed, addr, size, argv, argc, - NULL, "user", &uvmm->vmm); + ret = mmu->func->vmm.ctor(mmu, managed || raw, addr, size, + argv, argc, NULL, "user", &uvmm->vmm); if (ret) return ret; @@ -393,6 +569,7 @@ nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, uvmm->vmm = nvkm_vmm_ref(mmu->vmm); } + uvmm->vmm->managed.raw = raw; page = uvmm->vmm->func->page; args->v0.page_nr = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c index ae793f400ba1..eb5fcadcb39a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c @@ -676,41 +676,18 @@ nvkm_vmm_ptes_sparse(struct nvkm_vmm *vmm, u64 addr, u64 size, bool ref) return 0; } -static void -nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, - u64 addr, u64 size, bool sparse, bool pfn) -{ - const struct nvkm_vmm_desc_func *func = page->desc->func; - nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref", - false, pfn, nvkm_vmm_unref_ptes, NULL, NULL, - sparse ? func->sparse : func->invalid ? func->invalid : - func->unmap); -} - -static int -nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, - u64 addr, u64 size, struct nvkm_vmm_map *map, - nvkm_vmm_pte_func func) -{ - u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true, - false, nvkm_vmm_ref_ptes, func, map, NULL); - if (fail != ~0ULL) { - if ((size = fail - addr)) - nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false, false); - return -ENOMEM; - } - return 0; -} - static void nvkm_vmm_ptes_unmap(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, u64 addr, u64 size, bool sparse, bool pfn) { const struct nvkm_vmm_desc_func *func = page->desc->func; + + mutex_lock(&vmm->mutex.map); nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, pfn, NULL, NULL, NULL, sparse ? func->sparse : func->invalid ? func->invalid : func->unmap); + mutex_unlock(&vmm->mutex.map); } static void @@ -718,33 +695,108 @@ nvkm_vmm_ptes_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, u64 addr, u64 size, struct nvkm_vmm_map *map, nvkm_vmm_pte_func func) { + mutex_lock(&vmm->mutex.map); nvkm_vmm_iter(vmm, page, addr, size, "map", false, false, NULL, func, map, NULL); + mutex_unlock(&vmm->mutex.map); } static void -nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, - u64 addr, u64 size) +nvkm_vmm_ptes_put_locked(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) { nvkm_vmm_iter(vmm, page, addr, size, "unref", false, false, nvkm_vmm_unref_ptes, NULL, NULL, NULL); } +static void +nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) +{ + mutex_lock(&vmm->mutex.ref); + nvkm_vmm_ptes_put_locked(vmm, page, addr, size); + mutex_unlock(&vmm->mutex.ref); +} + static int nvkm_vmm_ptes_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, u64 addr, u64 size) { - u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, false, - nvkm_vmm_ref_ptes, NULL, NULL, NULL); + u64 fail; + + mutex_lock(&vmm->mutex.ref); + fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, false, + nvkm_vmm_ref_ptes, NULL, NULL, NULL); if (fail != ~0ULL) { if (fail != addr) - nvkm_vmm_ptes_put(vmm, page, addr, fail - addr); + nvkm_vmm_ptes_put_locked(vmm, page, addr, fail - addr); + mutex_unlock(&vmm->mutex.ref); + return -ENOMEM; + } + mutex_unlock(&vmm->mutex.ref); + return 0; +} + +static void +__nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, bool sparse, bool pfn) +{ + const struct nvkm_vmm_desc_func *func = page->desc->func; + + nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref", + false, pfn, nvkm_vmm_unref_ptes, NULL, NULL, + sparse ? func->sparse : func->invalid ? func->invalid : + func->unmap); +} + +static void +nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, bool sparse, bool pfn) +{ + if (vmm->managed.raw) { + nvkm_vmm_ptes_unmap(vmm, page, addr, size, sparse, pfn); + nvkm_vmm_ptes_put(vmm, page, addr, size); + } else { + __nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, sparse, pfn); + } +} + +static int +__nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, struct nvkm_vmm_map *map, + nvkm_vmm_pte_func func) +{ + u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true, + false, nvkm_vmm_ref_ptes, func, map, NULL); + if (fail != ~0ULL) { + if ((size = fail - addr)) + nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false, false); return -ENOMEM; } return 0; } -static inline struct nvkm_vma * +static int +nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, struct nvkm_vmm_map *map, + nvkm_vmm_pte_func func) +{ + int ret; + + if (vmm->managed.raw) { + ret = nvkm_vmm_ptes_get(vmm, page, addr, size); + if (ret) + return ret; + + nvkm_vmm_ptes_map(vmm, page, addr, size, map, func); + + return 0; + } else { + return __nvkm_vmm_ptes_get_map(vmm, page, addr, size, map, func); + } +} + +struct nvkm_vma * nvkm_vma_new(u64 addr, u64 size) { struct nvkm_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); @@ -1045,7 +1097,9 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, vmm->debug = mmu->subdev.debug; kref_init(&vmm->kref); - __mutex_init(&vmm->mutex, "&vmm->mutex", key ? key : &_key); + __mutex_init(&vmm->mutex.vmm, "&vmm->mutex.vmm", key ? key : &_key); + mutex_init(&vmm->mutex.ref); + mutex_init(&vmm->mutex.map); /* Locate the smallest page size supported by the backend, it will * have the deepest nesting of page tables. @@ -1101,6 +1155,9 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, if (addr && (ret = nvkm_vmm_ctor_managed(vmm, 0, addr))) return ret; + vmm->managed.p.addr = 0; + vmm->managed.p.size = addr; + /* NVKM-managed area. */ if (size) { if (!(vma = nvkm_vma_new(addr, size))) @@ -1114,6 +1171,9 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, size = vmm->limit - addr; if (size && (ret = nvkm_vmm_ctor_managed(vmm, addr, size))) return ret; + + vmm->managed.n.addr = addr; + vmm->managed.n.size = size; } else { /* Address-space fully managed by NVKM, requiring calls to * nvkm_vmm_get()/nvkm_vmm_put() to allocate address-space. @@ -1362,9 +1422,9 @@ void nvkm_vmm_unmap(struct nvkm_vmm *vmm, struct nvkm_vma *vma) { if (vma->memory) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); nvkm_vmm_unmap_locked(vmm, vma, false); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } } @@ -1423,6 +1483,8 @@ nvkm_vmm_map_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma, nvkm_vmm_pte_func func; int ret; + map->no_comp = vma->no_comp; + /* Make sure we won't overrun the end of the memory object. */ if (unlikely(nvkm_memory_size(map->memory) < map->offset + vma->size)) { VMM_DEBUG(vmm, "overrun %016llx %016llx %016llx", @@ -1507,10 +1569,15 @@ nvkm_vmm_map(struct nvkm_vmm *vmm, struct nvkm_vma *vma, void *argv, u32 argc, struct nvkm_vmm_map *map) { int ret; - mutex_lock(&vmm->mutex); + + if (nvkm_vmm_in_managed_range(vmm, vma->addr, vma->size) && + vmm->managed.raw) + return nvkm_vmm_map_locked(vmm, vma, argv, argc, map); + + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_map_locked(vmm, vma, argv, argc, map); vma->busy = false; - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); return ret; } @@ -1620,9 +1687,9 @@ nvkm_vmm_put(struct nvkm_vmm *vmm, struct nvkm_vma **pvma) { struct nvkm_vma *vma = *pvma; if (vma) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); nvkm_vmm_put_locked(vmm, vma); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); *pvma = NULL; } } @@ -1769,9 +1836,49 @@ int nvkm_vmm_get(struct nvkm_vmm *vmm, u8 page, u64 size, struct nvkm_vma **pvma) { int ret; - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = nvkm_vmm_get_locked(vmm, false, true, false, page, 0, size, pvma); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); + return ret; +} + +void +nvkm_vmm_raw_unmap(struct nvkm_vmm *vmm, u64 addr, u64 size, + bool sparse, u8 refd) +{ + const struct nvkm_vmm_page *page = &vmm->func->page[refd]; + + nvkm_vmm_ptes_unmap(vmm, page, addr, size, sparse, false); +} + +void +nvkm_vmm_raw_put(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd) +{ + const struct nvkm_vmm_page *page = vmm->func->page; + + nvkm_vmm_ptes_put(vmm, &page[refd], addr, size); +} + +int +nvkm_vmm_raw_get(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd) +{ + const struct nvkm_vmm_page *page = vmm->func->page; + + if (unlikely(!size)) + return -EINVAL; + + return nvkm_vmm_ptes_get(vmm, &page[refd], addr, size); +} + +int +nvkm_vmm_raw_sparse(struct nvkm_vmm *vmm, u64 addr, u64 size, bool ref) +{ + int ret; + + mutex_lock(&vmm->mutex.ref); + ret = nvkm_vmm_ptes_sparse(vmm, addr, size, ref); + mutex_unlock(&vmm->mutex.ref); + return ret; } @@ -1779,9 +1886,9 @@ void nvkm_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst) { if (inst && vmm && vmm->func->part) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); vmm->func->part(vmm, inst); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } } @@ -1790,9 +1897,9 @@ nvkm_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) { int ret = 0; if (vmm->func->join) { - mutex_lock(&vmm->mutex); + mutex_lock(&vmm->mutex.vmm); ret = vmm->func->join(vmm, inst); - mutex_unlock(&vmm->mutex); + mutex_unlock(&vmm->mutex.vmm); } return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h index f6188aa9171c..f9bc30cdb2b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h @@ -163,6 +163,7 @@ int nvkm_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, u32 pd_header, bool managed, u64 addr, u64 size, struct lock_class_key *, const char *name, struct nvkm_vmm **); +struct nvkm_vma *nvkm_vma_new(u64 addr, u64 size); struct nvkm_vma *nvkm_vmm_node_search(struct nvkm_vmm *, u64 addr); struct nvkm_vma *nvkm_vmm_node_split(struct nvkm_vmm *, struct nvkm_vma *, u64 addr, u64 size); @@ -173,6 +174,30 @@ void nvkm_vmm_put_locked(struct nvkm_vmm *, struct nvkm_vma *); void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *, bool pfn); void nvkm_vmm_unmap_region(struct nvkm_vmm *, struct nvkm_vma *); +int nvkm_vmm_raw_get(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd); +void nvkm_vmm_raw_put(struct nvkm_vmm *vmm, u64 addr, u64 size, u8 refd); +void nvkm_vmm_raw_unmap(struct nvkm_vmm *vmm, u64 addr, u64 size, + bool sparse, u8 refd); +int nvkm_vmm_raw_sparse(struct nvkm_vmm *, u64 addr, u64 size, bool ref); + +static inline bool +nvkm_vmm_in_managed_range(struct nvkm_vmm *vmm, u64 start, u64 size) +{ + u64 p_start = vmm->managed.p.addr; + u64 p_end = p_start + vmm->managed.p.size; + u64 n_start = vmm->managed.n.addr; + u64 n_end = n_start + vmm->managed.n.size; + u64 end = start + size; + + if (start >= p_start && end <= p_end) + return true; + + if (start >= n_start && end <= n_end) + return true; + + return false; +} + #define NVKM_VMM_PFN_ADDR 0xfffffffffffff000ULL #define NVKM_VMM_PFN_ADDR_SHIFT 12 #define NVKM_VMM_PFN_APER 0x00000000000000f0ULL diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c index 5438384d9a67..5e857c02e9aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c @@ -287,15 +287,17 @@ gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return -EINVAL; } - ret = nvkm_memory_tags_get(memory, device, tags, - nvkm_ltc_tags_clear, - &map->tags); - if (ret) { - VMM_DEBUG(vmm, "comp %d", ret); - return ret; + if (!map->no_comp) { + ret = nvkm_memory_tags_get(memory, device, tags, + nvkm_ltc_tags_clear, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } } - if (map->tags->mn) { + if (!map->no_comp && map->tags->mn) { u64 tags = map->tags->mn->offset + (map->offset >> 17); if (page->shift == 17 || !gm20x) { map->type |= tags << 44; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c index 17899fc95b2d..f3630d0e0d55 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c @@ -453,15 +453,17 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return -EINVAL; } - ret = nvkm_memory_tags_get(memory, device, tags, - nvkm_ltc_tags_clear, - &map->tags); - if (ret) { - VMM_DEBUG(vmm, "comp %d", ret); - return ret; + if (!map->no_comp) { + ret = nvkm_memory_tags_get(memory, device, tags, + nvkm_ltc_tags_clear, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } } - if (map->tags->mn) { + if (!map->no_comp && map->tags->mn) { tags = map->tags->mn->offset + (map->offset >> 16); map->ctag |= ((1ULL << page->shift) >> 16) << 36; map->type |= tags << 36; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c index b7548dcd72c7..ff08ad5005a9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c @@ -296,19 +296,22 @@ nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return -EINVAL; } - ret = nvkm_memory_tags_get(memory, device, tags, NULL, - &map->tags); - if (ret) { - VMM_DEBUG(vmm, "comp %d", ret); - return ret; - } + if (!map->no_comp) { + ret = nvkm_memory_tags_get(memory, device, tags, NULL, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } - if (map->tags->mn) { - u32 tags = map->tags->mn->offset + (map->offset >> 16); - map->ctag |= (u64)comp << 49; - map->type |= (u64)comp << 47; - map->type |= (u64)tags << 49; - map->next |= map->ctag; + if (map->tags->mn) { + u32 tags = map->tags->mn->offset + + (map->offset >> 16); + map->ctag |= (u64)comp << 49; + map->type |= (u64)comp << 47; + map->type |= (u64)tags << 49; + map->next |= map->ctag; + } } } From patchwork Fri Aug 4 18:23:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131311 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp45201vqr; Fri, 4 Aug 2023 12:09:12 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGp7CztQ3nDc7W/yXXwEfQt3yM5TwyJS8Hz1zgW50FZ43DTkDSGuIFvSSaxbAE8EYRKMlhE X-Received: by 2002:a05:6a00:2e0f:b0:686:2668:796f with SMTP id fc15-20020a056a002e0f00b006862668796fmr2826653pfb.32.1691176152147; Fri, 04 Aug 2023 12:09:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691176152; cv=none; d=google.com; s=arc-20160816; b=bLr5CJkzA3JHmK33+nlXIvOBeONQKclvp+bwlgwPtzl774yzGu53lBhPimssyYqFPj 6LWqYMx3FNWO7DZsVzhloC/cHu+5gb1eCFB7rAUR/JuFGLzNPLRDtaDxOSLAvVehGqO7 DM8nhXB01UVoSQWhVazWAVrpUctR+Lm83p6Bm9LDD9QUIx3I//gTyXBwp6qaRVw4dZZw qbMv3DTKVPTfmezFe781ZlXu5ECmHcC15muwSJiB764DqXn+5q0HN8qddOITAjmMxuDZ BHk2mx2deUZeWnEaIppgLbYxalaaCfu652hc4WFGtlTYZSci+vwGSMeGTgyMaC46VZul XEJA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=W5Z69duQZZHczdNva7OYriVP022eEP31h8SDSDX32NU=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=Z5V5cxCMfvMdBmV6yUb4KLBbsrFkczpw62TM93Rf7y2WjX0erK29dKsuEswDKKa1VJ QfM8cId0RVTAhHPryThtbe3yGY/nEV7g5zpc90/5Fp7RuJQAcbKjBrDTzUYITishdACp r7zbJxbTvyWh5rmtziJCxDw+AkuztEbB25Ju6gGsZVfgMIiDz/5G3Hf9MXX7+GTyL3c4 8Y2j3LH3WOdL8aKhR/RwNrAJfwJTlQLPqLEe/CNzYFopcGB0UDxJggJP6rpsbNTtC3UG pVpCfWjvArCsiNDv6YL3hpifFEo9LbpFX1jnRNUhFQMs66mK0ImUPvHN/2up40bjdOII KaKg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Ig5tYoWw; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id k188-20020a633dc5000000b00564ac9f249esi2136865pga.312.2023.08.04.12.08.58; Fri, 04 Aug 2023 12:09:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=Ig5tYoWw; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231411AbjHDS1n (ORCPT + 99 others); Fri, 4 Aug 2023 14:27:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53882 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231381AbjHDS0Q (ORCPT ); Fri, 4 Aug 2023 14:26:16 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A44FE5251 for ; Fri, 4 Aug 2023 11:25:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173507; 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=W5Z69duQZZHczdNva7OYriVP022eEP31h8SDSDX32NU=; b=Ig5tYoWwZWbQPYax3nr0ymzAtG6pKLSkLBapeec0WqsTo+NAkkcTqQIQdWD09VAWk0FvFx ta4ejpIr0+O24WGZuwxRkg2+Ktspp8SyWnGm/UQU+zUQTMwL/KrGZQrA8IZfLRaDGN2vK6 2crsJ9BAAnFVL69oDNgAw5L1QYEjQM4= Received: from mail-lj1-f199.google.com (mail-lj1-f199.google.com [209.85.208.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-256-2_av8hkVNOynSxt83Ozegw-1; Fri, 04 Aug 2023 14:25:06 -0400 X-MC-Unique: 2_av8hkVNOynSxt83Ozegw-1 Received: by mail-lj1-f199.google.com with SMTP id 38308e7fff4ca-2b9e8abe56bso23737831fa.2 for ; Fri, 04 Aug 2023 11:25:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173504; x=1691778304; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=W5Z69duQZZHczdNva7OYriVP022eEP31h8SDSDX32NU=; b=d9Q6OGaZ6fOgEX574JmVJGe+8tfaFS6nWBmmv6y5/5mJfcUX6mE0WooAxoKOJhIJmp gH4rrTzyhJ90wlhYL6pS8x11Qcqp/bSvFSCHt2d1NGqHxibRwN6s8NEZxJxCeirYjJQV j0aoGKX4ZG4gO9m+7eIJDQvCbSX4AP9wi636KjchetwgcU1a8Yc7DITyrxKC/aQzzEmQ 5Tb0goBQ06HPNShL8/TROxiJ3+SD/rp0730aP1dJPeF3mKsoSlrNhooc0yRpBWFutJqR oReT0vIE9mrf7GBhI4OllBPQs+KR4tc2mMtuVmAf8aX59zo+e+JYhHbhem34VdKE/OAD on6A== X-Gm-Message-State: AOJu0YzTHteoZnIWlz+byxWMj+r/DBcNM9gjKMeZwn6B86At4YFxb+CC 68KXI+oEIeU2XlivGE0LjypWUxPcj3PH56hzdtBnm9/EpR6D4S3WV6vW+Qm5ZH/XQ3juGOe6TXv CgIeXbRQO1nMQKMkO5vZTd8zx X-Received: by 2002:a19:9156:0:b0:4fb:79b5:5512 with SMTP id y22-20020a199156000000b004fb79b55512mr1680443lfj.66.1691173503064; Fri, 04 Aug 2023 11:25:03 -0700 (PDT) X-Received: by 2002:a19:9156:0:b0:4fb:79b5:5512 with SMTP id y22-20020a199156000000b004fb79b55512mr1680408lfj.66.1691173502238; Fri, 04 Aug 2023 11:25:02 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id e26-20020a50ec9a000000b0051873c201a0sm1568445edr.26.2023.08.04.11.25.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:25:01 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 11/12] drm/nouveau: implement new VM_BIND uAPI Date: Fri, 4 Aug 2023 20:23:51 +0200 Message-ID: <20230804182406.5222-12-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773326725357805495 X-GMAIL-MSGID: 1773326725357805495 This commit provides the implementation for the new uapi motivated by the Vulkan API. It allows user mode drivers (UMDs) to: 1) Initialize a GPU virtual address (VA) space via the new DRM_IOCTL_NOUVEAU_VM_INIT ioctl for UMDs to specify the portion of VA space managed by the kernel and userspace, respectively. 2) Allocate and free a VA space region as well as bind and unbind memory to the GPUs VA space via the new DRM_IOCTL_NOUVEAU_VM_BIND ioctl. UMDs can request the named operations to be processed either synchronously or asynchronously. It supports DRM syncobjs (incl. timelines) as synchronization mechanism. The management of the GPU VA mappings is implemented with the DRM GPU VA manager. 3) Execute push buffers with the new DRM_IOCTL_NOUVEAU_EXEC ioctl. The execution happens asynchronously. It supports DRM syncobj (incl. timelines) as synchronization mechanism. DRM GEM object locking is handled with drm_exec. Both, DRM_IOCTL_NOUVEAU_VM_BIND and DRM_IOCTL_NOUVEAU_EXEC, use the DRM GPU scheduler for the asynchronous paths. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- Documentation/gpu/driver-uapi.rst | 3 + drivers/gpu/drm/nouveau/Kbuild | 3 + drivers/gpu/drm/nouveau/Kconfig | 2 + drivers/gpu/drm/nouveau/nouveau_abi16.c | 24 + drivers/gpu/drm/nouveau/nouveau_abi16.h | 1 + drivers/gpu/drm/nouveau/nouveau_bo.c | 159 +- drivers/gpu/drm/nouveau/nouveau_bo.h | 3 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 27 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 58 +- drivers/gpu/drm/nouveau/nouveau_exec.c | 411 +++++ drivers/gpu/drm/nouveau/nouveau_exec.h | 54 + drivers/gpu/drm/nouveau/nouveau_gem.c | 49 +- drivers/gpu/drm/nouveau/nouveau_gem.h | 3 +- drivers/gpu/drm/nouveau/nouveau_mem.h | 5 + drivers/gpu/drm/nouveau/nouveau_prime.c | 13 +- drivers/gpu/drm/nouveau/nouveau_sched.c | 419 +++++ drivers/gpu/drm/nouveau/nouveau_sched.h | 127 ++ drivers/gpu/drm/nouveau/nouveau_uvmm.c | 1921 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_uvmm.h | 108 ++ 19 files changed, 3321 insertions(+), 69 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nouveau_exec.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_exec.h create mode 100644 drivers/gpu/drm/nouveau/nouveau_sched.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_sched.h create mode 100644 drivers/gpu/drm/nouveau/nouveau_uvmm.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_uvmm.h diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst index 9c7ca6e33a68..c08bcbb95fb3 100644 --- a/Documentation/gpu/driver-uapi.rst +++ b/Documentation/gpu/driver-uapi.rst @@ -13,4 +13,7 @@ drm/nouveau uAPI VM_BIND / EXEC uAPI ------------------- +.. kernel-doc:: drivers/gpu/drm/nouveau/nouveau_exec.c + :doc: Overview + .. kernel-doc:: include/uapi/drm/nouveau_drm.h diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index 5e5617006da5..cf6b3a80c0c8 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -47,6 +47,9 @@ nouveau-y += nouveau_prime.o nouveau-y += nouveau_sgdma.o nouveau-y += nouveau_ttm.o nouveau-y += nouveau_vmm.o +nouveau-y += nouveau_exec.o +nouveau-y += nouveau_sched.o +nouveau-y += nouveau_uvmm.o # DRM - modesetting nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index a70bd65e1400..c52e8096cca4 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -10,6 +10,8 @@ config DRM_NOUVEAU select DRM_KMS_HELPER select DRM_TTM select DRM_TTM_HELPER + select DRM_EXEC + select DRM_SCHED select I2C select I2C_ALGOBIT select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 82dab51d8aeb..30afbec9e3b1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -35,6 +35,7 @@ #include "nouveau_chan.h" #include "nouveau_abi16.h" #include "nouveau_vmm.h" +#include "nouveau_sched.h" static struct nouveau_abi16 * nouveau_abi16(struct drm_file *file_priv) @@ -125,6 +126,17 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, { struct nouveau_abi16_ntfy *ntfy, *temp; + /* When a client exits without waiting for it's queued up jobs to + * finish it might happen that we fault the channel. This is due to + * drm_file_free() calling drm_gem_release() before the postclose() + * callback. Hence, we can't tear down this scheduler entity before + * uvmm mappings are unmapped. Currently, we can't detect this case. + * + * However, this should be rare and harmless, since the channel isn't + * needed anymore. + */ + nouveau_sched_entity_fini(&chan->sched_entity); + /* wait for all activity to stop before cleaning up */ if (chan->chan) nouveau_channel_idle(chan->chan); @@ -261,6 +273,13 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) if (!drm->channel) return nouveau_abi16_put(abi16, -ENODEV); + /* If uvmm wasn't initialized until now disable it completely to prevent + * userspace from mixing up UAPIs. + * + * The client lock is already acquired by nouveau_abi16_get(). + */ + __nouveau_cli_disable_uvmm_noinit(cli); + device = &abi16->device; engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR; @@ -304,6 +323,11 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) if (ret) goto done; + ret = nouveau_sched_entity_init(&chan->sched_entity, &drm->sched, + drm->sched_wq); + if (ret) + goto done; + init->channel = chan->chan->chid; if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index d5d80d0d9011..9f538486c10e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -26,6 +26,7 @@ struct nouveau_abi16_chan { struct nouveau_bo *ntfy; struct nouveau_vma *ntfy_vma; struct nvkm_mm heap; + struct nouveau_sched_entity sched_entity; }; struct nouveau_abi16 { diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e38e448d9632..19cab37ac69c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -199,7 +199,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, u64 *size) struct nouveau_bo * nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, - u32 tile_mode, u32 tile_flags) + u32 tile_mode, u32 tile_flags, bool internal) { struct nouveau_drm *drm = cli->drm; struct nouveau_bo *nvbo; @@ -233,68 +233,103 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, nvbo->force_coherent = true; } - if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) { - nvbo->kind = (tile_flags & 0x0000ff00) >> 8; - if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { - kfree(nvbo); - return ERR_PTR(-EINVAL); + nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG); + if (!nouveau_cli_uvmm(cli) || internal) { + /* for BO noVM allocs, don't assign kinds */ + if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) { + nvbo->kind = (tile_flags & 0x0000ff00) >> 8; + if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { + kfree(nvbo); + return ERR_PTR(-EINVAL); + } + + nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; + } else if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { + nvbo->kind = (tile_flags & 0x00007f00) >> 8; + nvbo->comp = (tile_flags & 0x00030000) >> 16; + if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { + kfree(nvbo); + return ERR_PTR(-EINVAL); + } + } else { + nvbo->zeta = (tile_flags & 0x00000007); } + nvbo->mode = tile_mode; + + /* Determine the desirable target GPU page size for the buffer. */ + for (i = 0; i < vmm->page_nr; i++) { + /* Because we cannot currently allow VMM maps to fail + * during buffer migration, we need to determine page + * size for the buffer up-front, and pre-allocate its + * page tables. + * + * Skip page sizes that can't support needed domains. + */ + if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE && + (domain & NOUVEAU_GEM_DOMAIN_VRAM) && !vmm->page[i].vram) + continue; + if ((domain & NOUVEAU_GEM_DOMAIN_GART) && + (!vmm->page[i].host || vmm->page[i].shift > PAGE_SHIFT)) + continue; - nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; - } else - if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - nvbo->kind = (tile_flags & 0x00007f00) >> 8; - nvbo->comp = (tile_flags & 0x00030000) >> 16; - if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { + /* Select this page size if it's the first that supports + * the potential memory domains, or when it's compatible + * with the requested compression settings. + */ + if (pi < 0 || !nvbo->comp || vmm->page[i].comp) + pi = i; + + /* Stop once the buffer is larger than the current page size. */ + if (*size >= 1ULL << vmm->page[i].shift) + break; + } + + if (WARN_ON(pi < 0)) { kfree(nvbo); return ERR_PTR(-EINVAL); } - } else { - nvbo->zeta = (tile_flags & 0x00000007); - } - nvbo->mode = tile_mode; - nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG); - - /* Determine the desirable target GPU page size for the buffer. */ - for (i = 0; i < vmm->page_nr; i++) { - /* Because we cannot currently allow VMM maps to fail - * during buffer migration, we need to determine page - * size for the buffer up-front, and pre-allocate its - * page tables. - * - * Skip page sizes that can't support needed domains. - */ - if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE && - (domain & NOUVEAU_GEM_DOMAIN_VRAM) && !vmm->page[i].vram) - continue; - if ((domain & NOUVEAU_GEM_DOMAIN_GART) && - (!vmm->page[i].host || vmm->page[i].shift > PAGE_SHIFT)) - continue; - - /* Select this page size if it's the first that supports - * the potential memory domains, or when it's compatible - * with the requested compression settings. - */ - if (pi < 0 || !nvbo->comp || vmm->page[i].comp) - pi = i; - /* Stop once the buffer is larger than the current page size. */ - if (*size >= 1ULL << vmm->page[i].shift) - break; - } + /* Disable compression if suitable settings couldn't be found. */ + if (nvbo->comp && !vmm->page[pi].comp) { + if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100) + nvbo->kind = mmu->kind[nvbo->kind]; + nvbo->comp = 0; + } + nvbo->page = vmm->page[pi].shift; + } else { + /* reject other tile flags when in VM mode. */ + if (tile_mode) + return ERR_PTR(-EINVAL); + if (tile_flags & ~NOUVEAU_GEM_TILE_NONCONTIG) + return ERR_PTR(-EINVAL); - if (WARN_ON(pi < 0)) { - kfree(nvbo); - return ERR_PTR(-EINVAL); - } + /* Determine the desirable target GPU page size for the buffer. */ + for (i = 0; i < vmm->page_nr; i++) { + /* Because we cannot currently allow VMM maps to fail + * during buffer migration, we need to determine page + * size for the buffer up-front, and pre-allocate its + * page tables. + * + * Skip page sizes that can't support needed domains. + */ + if ((domain & NOUVEAU_GEM_DOMAIN_VRAM) && !vmm->page[i].vram) + continue; + if ((domain & NOUVEAU_GEM_DOMAIN_GART) && + (!vmm->page[i].host || vmm->page[i].shift > PAGE_SHIFT)) + continue; - /* Disable compression if suitable settings couldn't be found. */ - if (nvbo->comp && !vmm->page[pi].comp) { - if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100) - nvbo->kind = mmu->kind[nvbo->kind]; - nvbo->comp = 0; + if (pi < 0) + pi = i; + /* Stop once the buffer is larger than the current page size. */ + if (*size >= 1ULL << vmm->page[i].shift) + break; + } + if (WARN_ON(pi < 0)) { + kfree(nvbo); + return ERR_PTR(-EINVAL); + } + nvbo->page = vmm->page[pi].shift; } - nvbo->page = vmm->page[pi].shift; nouveau_bo_fixup_align(nvbo, align, size); @@ -307,18 +342,26 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 domain, { int type = sg ? ttm_bo_type_sg : ttm_bo_type_device; int ret; + struct ttm_operation_ctx ctx = { + .interruptible = false, + .no_wait_gpu = false, + .resv = robj, + }; nouveau_bo_placement_set(nvbo, domain, 0); INIT_LIST_HEAD(&nvbo->io_reserve_lru); - ret = ttm_bo_init_validate(nvbo->bo.bdev, &nvbo->bo, type, - &nvbo->placement, align >> PAGE_SHIFT, false, + ret = ttm_bo_init_reserved(nvbo->bo.bdev, &nvbo->bo, type, + &nvbo->placement, align >> PAGE_SHIFT, &ctx, sg, robj, nouveau_bo_del_ttm); if (ret) { /* ttm will call nouveau_bo_del_ttm if it fails.. */ return ret; } + if (!robj) + ttm_bo_unreserve(&nvbo->bo); + return 0; } @@ -332,7 +375,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, int ret; nvbo = nouveau_bo_alloc(cli, &size, &align, domain, tile_mode, - tile_flags); + tile_flags, true); if (IS_ERR(nvbo)) return PTR_ERR(nvbo); @@ -951,6 +994,7 @@ static void nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, list_for_each_entry(vma, &nvbo->vma_list, head) { nouveau_vma_map(vma, mem); } + nouveau_uvmm_bo_map_all(nvbo, mem); } else { list_for_each_entry(vma, &nvbo->vma_list, head) { ret = dma_resv_wait_timeout(bo->base.resv, @@ -959,6 +1003,7 @@ static void nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, WARN_ON(ret <= 0); nouveau_vma_unmap(vma); } + nouveau_uvmm_bo_unmap_all(nvbo); } if (new_reg) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index 774dd93ca76b..07f671cf895e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -26,6 +26,7 @@ struct nouveau_bo { struct list_head entry; int pbbo_index; bool validate_mapped; + bool no_share; /* GPU address space is independent of CPU word size */ uint64_t offset; @@ -73,7 +74,7 @@ extern struct ttm_device_funcs nouveau_bo_driver; void nouveau_bo_move_init(struct nouveau_drm *); struct nouveau_bo *nouveau_bo_alloc(struct nouveau_cli *, u64 *size, int *align, - u32 domain, u32 tile_mode, u32 tile_flags); + u32 domain, u32 tile_mode, u32 tile_flags, bool internal); int nouveau_bo_init(struct nouveau_bo *, u64 size, int align, u32 domain, struct sg_table *sg, struct dma_resv *robj); int nouveau_bo_new(struct nouveau_cli *, u64 size, int align, u32 domain, diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 8325fcf35c5e..4396f501b16a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -68,6 +68,9 @@ #include "nouveau_platform.h" #include "nouveau_svm.h" #include "nouveau_dmem.h" +#include "nouveau_exec.h" +#include "nouveau_uvmm.h" +#include "nouveau_sched.h" DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0, "DRM_UT_CORE", @@ -196,6 +199,8 @@ nouveau_cli_fini(struct nouveau_cli *cli) WARN_ON(!list_empty(&cli->worker)); usif_client_fini(cli); + nouveau_uvmm_fini(&cli->uvmm); + nouveau_sched_entity_fini(&cli->sched_entity); nouveau_vmm_fini(&cli->svm); nouveau_vmm_fini(&cli->vmm); nvif_mmu_dtor(&cli->mmu); @@ -301,6 +306,12 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname, } cli->mem = &mems[ret]; + + ret = nouveau_sched_entity_init(&cli->sched_entity, &drm->sched, + drm->sched_wq); + if (ret) + goto done; + return 0; done: if (ret) @@ -568,10 +579,14 @@ nouveau_drm_device_init(struct drm_device *dev) nvif_parent_ctor(&nouveau_parent, &drm->parent); drm->master.base.object.parent = &drm->parent; - ret = nouveau_cli_init(drm, "DRM-master", &drm->master); + ret = nouveau_sched_init(drm); if (ret) goto fail_alloc; + ret = nouveau_cli_init(drm, "DRM-master", &drm->master); + if (ret) + goto fail_sched; + ret = nouveau_cli_init(drm, "DRM", &drm->client); if (ret) goto fail_master; @@ -628,7 +643,6 @@ nouveau_drm_device_init(struct drm_device *dev) } return 0; - fail_dispinit: nouveau_display_destroy(dev); fail_dispctor: @@ -641,6 +655,8 @@ nouveau_drm_device_init(struct drm_device *dev) nouveau_cli_fini(&drm->client); fail_master: nouveau_cli_fini(&drm->master); +fail_sched: + nouveau_sched_fini(drm); fail_alloc: nvif_parent_dtor(&drm->parent); kfree(drm); @@ -692,6 +708,8 @@ nouveau_drm_device_fini(struct drm_device *dev) } mutex_unlock(&drm->clients_lock); + nouveau_sched_fini(drm); + nouveau_cli_fini(&drm->client); nouveau_cli_fini(&drm->master); nvif_parent_dtor(&drm->parent); @@ -1193,6 +1211,9 @@ nouveau_ioctls[] = { DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_VM_INIT, nouveau_uvmm_ioctl_vm_init, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_VM_BIND, nouveau_uvmm_ioctl_vm_bind, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_EXEC, nouveau_exec_ioctl_exec, DRM_RENDER_ALLOW), }; long @@ -1240,6 +1261,8 @@ nouveau_driver_fops = { static struct drm_driver driver_stub = { .driver_features = DRIVER_GEM | + DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE | + DRIVER_GEM_GPUVA | DRIVER_MODESET | DRIVER_RENDER, .open = nouveau_drm_open, diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index d28236021971..1fe17ff95f5e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -10,8 +10,8 @@ #define DRIVER_DATE "20120801" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 3 -#define DRIVER_PATCHLEVEL 1 +#define DRIVER_MINOR 4 +#define DRIVER_PATCHLEVEL 0 /* * 1.1.1: @@ -63,7 +63,9 @@ struct platform_device; #include "nouveau_fence.h" #include "nouveau_bios.h" +#include "nouveau_sched.h" #include "nouveau_vmm.h" +#include "nouveau_uvmm.h" struct nouveau_drm_tile { struct nouveau_fence *fence; @@ -91,6 +93,10 @@ struct nouveau_cli { struct nvif_mmu mmu; struct nouveau_vmm vmm; struct nouveau_vmm svm; + struct nouveau_uvmm uvmm; + + struct nouveau_sched_entity sched_entity; + const struct nvif_mclass *mem; struct list_head head; @@ -112,15 +118,59 @@ struct nouveau_cli_work { struct dma_fence_cb cb; }; +static inline struct nouveau_uvmm * +nouveau_cli_uvmm(struct nouveau_cli *cli) +{ + if (!cli || !cli->uvmm.vmm.cli) + return NULL; + + return &cli->uvmm; +} + +static inline struct nouveau_uvmm * +nouveau_cli_uvmm_locked(struct nouveau_cli *cli) +{ + struct nouveau_uvmm *uvmm; + + mutex_lock(&cli->mutex); + uvmm = nouveau_cli_uvmm(cli); + mutex_unlock(&cli->mutex); + + return uvmm; +} + static inline struct nouveau_vmm * nouveau_cli_vmm(struct nouveau_cli *cli) { + struct nouveau_uvmm *uvmm; + + uvmm = nouveau_cli_uvmm(cli); + if (uvmm) + return &uvmm->vmm; + if (cli->svm.cli) return &cli->svm; return &cli->vmm; } +static inline void +__nouveau_cli_disable_uvmm_noinit(struct nouveau_cli *cli) +{ + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); + + if (!uvmm) + cli->uvmm.disabled = true; +} + +static inline void +nouveau_cli_disable_uvmm_noinit(struct nouveau_cli *cli) +{ + mutex_lock(&cli->mutex); + __nouveau_cli_disable_uvmm_noinit(cli); + mutex_unlock(&cli->mutex); +} + void nouveau_cli_work_queue(struct nouveau_cli *, struct dma_fence *, struct nouveau_cli_work *); @@ -257,6 +307,10 @@ struct nouveau_drm { struct mutex lock; bool component_registered; } audio; + + struct drm_gpu_scheduler sched; + struct workqueue_struct *sched_wq; + }; static inline struct nouveau_drm * diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c new file mode 100644 index 000000000000..42d9dd43ea02 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: MIT + +#include + +#include "nouveau_drv.h" +#include "nouveau_gem.h" +#include "nouveau_mem.h" +#include "nouveau_dma.h" +#include "nouveau_exec.h" +#include "nouveau_abi16.h" +#include "nouveau_chan.h" +#include "nouveau_sched.h" +#include "nouveau_uvmm.h" + +/** + * DOC: Overview + * + * Nouveau's VM_BIND / EXEC UAPI consists of three ioctls: DRM_NOUVEAU_VM_INIT, + * DRM_NOUVEAU_VM_BIND and DRM_NOUVEAU_EXEC. + * + * In order to use the UAPI firstly a user client must initialize the VA space + * using the DRM_NOUVEAU_VM_INIT ioctl specifying which region of the VA space + * should be managed by the kernel and which by the UMD. + * + * The DRM_NOUVEAU_VM_BIND ioctl provides clients an interface to manage the + * userspace-managable portion of the VA space. It provides operations to map + * and unmap memory. Mappings may be flagged as sparse. Sparse mappings are not + * backed by a GEM object and the kernel will ignore GEM handles provided + * alongside a sparse mapping. + * + * Userspace may request memory backed mappings either within or outside of the + * bounds (but not crossing those bounds) of a previously mapped sparse + * mapping. Subsequently requested memory backed mappings within a sparse + * mapping will take precedence over the corresponding range of the sparse + * mapping. If such memory backed mappings are unmapped the kernel will make + * sure that the corresponding sparse mapping will take their place again. + * Requests to unmap a sparse mapping that still contains memory backed mappings + * will result in those memory backed mappings being unmapped first. + * + * Unmap requests are not bound to the range of existing mappings and can even + * overlap the bounds of sparse mappings. For such a request the kernel will + * make sure to unmap all memory backed mappings within the given range, + * splitting up memory backed mappings which are only partially contained + * within the given range. Unmap requests with the sparse flag set must match + * the range of a previously mapped sparse mapping exactly though. + * + * While the kernel generally permits arbitrary sequences and ranges of memory + * backed mappings being mapped and unmapped, either within a single or multiple + * VM_BIND ioctl calls, there are some restrictions for sparse mappings. + * + * The kernel does not permit to: + * - unmap non-existent sparse mappings + * - unmap a sparse mapping and map a new sparse mapping overlapping the range + * of the previously unmapped sparse mapping within the same VM_BIND ioctl + * - unmap a sparse mapping and map new memory backed mappings overlapping the + * range of the previously unmapped sparse mapping within the same VM_BIND + * ioctl + * + * When using the VM_BIND ioctl to request the kernel to map memory to a given + * virtual address in the GPU's VA space there is no guarantee that the actual + * mappings are created in the GPU's MMU. If the given memory is swapped out + * at the time the bind operation is executed the kernel will stash the mapping + * details into it's internal alloctor and create the actual MMU mappings once + * the memory is swapped back in. While this is transparent for userspace, it is + * guaranteed that all the backing memory is swapped back in and all the memory + * mappings, as requested by userspace previously, are actually mapped once the + * DRM_NOUVEAU_EXEC ioctl is called to submit an exec job. + * + * A VM_BIND job can be executed either synchronously or asynchronously. If + * exectued asynchronously, userspace may provide a list of syncobjs this job + * will wait for and/or a list of syncobj the kernel will signal once the + * VM_BIND job finished execution. If executed synchronously the ioctl will + * block until the bind job is finished. For synchronous jobs the kernel will + * not permit any syncobjs submitted to the kernel. + * + * To execute a push buffer the UAPI provides the DRM_NOUVEAU_EXEC ioctl. EXEC + * jobs are always executed asynchronously, and, equal to VM_BIND jobs, provide + * the option to synchronize them with syncobjs. + * + * Besides that, EXEC jobs can be scheduled for a specified channel to execute on. + * + * Since VM_BIND jobs update the GPU's VA space on job submit, EXEC jobs do have + * an up to date view of the VA space. However, the actual mappings might still + * be pending. Hence, EXEC jobs require to have the particular fences - of + * the corresponding VM_BIND jobs they depent on - attached to them. + */ + +static int +nouveau_exec_job_submit(struct nouveau_job *job) +{ + struct nouveau_exec_job *exec_job = to_nouveau_exec_job(job); + struct nouveau_cli *cli = job->cli; + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); + struct drm_exec *exec = &job->exec; + struct drm_gem_object *obj; + unsigned long index; + int ret; + + ret = nouveau_fence_new(&exec_job->fence); + if (ret) + return ret; + + nouveau_uvmm_lock(uvmm); + drm_exec_init(exec, DRM_EXEC_INTERRUPTIBLE_WAIT | + DRM_EXEC_IGNORE_DUPLICATES); + drm_exec_until_all_locked(exec) { + struct drm_gpuva *va; + + drm_gpuva_for_each_va(va, &uvmm->umgr) { + if (unlikely(va == &uvmm->umgr.kernel_alloc_node)) + continue; + + ret = drm_exec_prepare_obj(exec, va->gem.obj, 1); + drm_exec_retry_on_contention(exec); + if (ret) + goto err_uvmm_unlock; + } + } + nouveau_uvmm_unlock(uvmm); + + drm_exec_for_each_locked_object(exec, index, obj) { + struct nouveau_bo *nvbo = nouveau_gem_object(obj); + + ret = nouveau_bo_validate(nvbo, true, false); + if (ret) + goto err_exec_fini; + } + + return 0; + +err_uvmm_unlock: + nouveau_uvmm_unlock(uvmm); +err_exec_fini: + drm_exec_fini(exec); + return ret; + +} + +static void +nouveau_exec_job_armed_submit(struct nouveau_job *job) +{ + struct drm_exec *exec = &job->exec; + struct drm_gem_object *obj; + unsigned long index; + + drm_exec_for_each_locked_object(exec, index, obj) + dma_resv_add_fence(obj->resv, job->done_fence, job->resv_usage); + + drm_exec_fini(exec); +} + +static struct dma_fence * +nouveau_exec_job_run(struct nouveau_job *job) +{ + struct nouveau_exec_job *exec_job = to_nouveau_exec_job(job); + struct nouveau_channel *chan = exec_job->chan; + struct nouveau_fence *fence = exec_job->fence; + int i, ret; + + ret = nouveau_dma_wait(chan, exec_job->push.count + 1, 16); + if (ret) { + NV_PRINTK(err, job->cli, "nv50cal_space: %d\n", ret); + return ERR_PTR(ret); + } + + for (i = 0; i < exec_job->push.count; i++) { + nv50_dma_push(chan, exec_job->push.s[i].va, + exec_job->push.s[i].va_len); + } + + ret = nouveau_fence_emit(fence, chan); + if (ret) { + NV_PRINTK(err, job->cli, "error fencing pushbuf: %d\n", ret); + WIND_RING(chan); + return ERR_PTR(ret); + } + + exec_job->fence = NULL; + + return &fence->base; +} + +static void +nouveau_exec_job_free(struct nouveau_job *job) +{ + struct nouveau_exec_job *exec_job = to_nouveau_exec_job(job); + + nouveau_job_free(job); + + nouveau_fence_unref(&exec_job->fence); + kfree(exec_job->push.s); + kfree(exec_job); +} + +static enum drm_gpu_sched_stat +nouveau_exec_job_timeout(struct nouveau_job *job) +{ + struct nouveau_exec_job *exec_job = to_nouveau_exec_job(job); + struct nouveau_channel *chan = exec_job->chan; + + if (unlikely(!atomic_read(&chan->killed))) + nouveau_channel_kill(chan); + + NV_PRINTK(warn, job->cli, "job timeout, channel %d killed!\n", + chan->chid); + + nouveau_sched_entity_fini(job->entity); + + return DRM_GPU_SCHED_STAT_ENODEV; +} + +static struct nouveau_job_ops nouveau_exec_job_ops = { + .submit = nouveau_exec_job_submit, + .armed_submit = nouveau_exec_job_armed_submit, + .run = nouveau_exec_job_run, + .free = nouveau_exec_job_free, + .timeout = nouveau_exec_job_timeout, +}; + +int +nouveau_exec_job_init(struct nouveau_exec_job **pjob, + struct nouveau_exec_job_args *__args) +{ + struct nouveau_exec_job *job; + struct nouveau_job_args args = {}; + int ret; + + job = *pjob = kzalloc(sizeof(*job), GFP_KERNEL); + if (!job) + return -ENOMEM; + + job->push.count = __args->push.count; + if (__args->push.count) { + job->push.s = kmemdup(__args->push.s, + sizeof(*__args->push.s) * + __args->push.count, + GFP_KERNEL); + if (!job->push.s) { + ret = -ENOMEM; + goto err_free_job; + } + } + + job->chan = __args->chan; + + args.sched_entity = __args->sched_entity; + args.file_priv = __args->file_priv; + + args.in_sync.count = __args->in_sync.count; + args.in_sync.s = __args->in_sync.s; + + args.out_sync.count = __args->out_sync.count; + args.out_sync.s = __args->out_sync.s; + + args.ops = &nouveau_exec_job_ops; + args.resv_usage = DMA_RESV_USAGE_WRITE; + + ret = nouveau_job_init(&job->base, &args); + if (ret) + goto err_free_pushs; + + return 0; + +err_free_pushs: + kfree(job->push.s); +err_free_job: + kfree(job); + *pjob = NULL; + + return ret; +} + +static int +nouveau_exec(struct nouveau_exec_job_args *args) +{ + struct nouveau_exec_job *job; + int ret; + + ret = nouveau_exec_job_init(&job, args); + if (ret) + return ret; + + ret = nouveau_job_submit(&job->base); + if (ret) + goto err_job_fini; + + return 0; + +err_job_fini: + nouveau_job_fini(&job->base); + return ret; +} + +static int +nouveau_exec_ucopy(struct nouveau_exec_job_args *args, + struct drm_nouveau_exec __user *req) +{ + struct drm_nouveau_sync **s; + u32 inc = req->wait_count; + u64 ins = req->wait_ptr; + u32 outc = req->sig_count; + u64 outs = req->sig_ptr; + u32 pushc = req->push_count; + u64 pushs = req->push_ptr; + int ret; + + if (pushc) { + args->push.count = pushc; + args->push.s = u_memcpya(pushs, pushc, sizeof(*args->push.s)); + if (IS_ERR(args->push.s)) + return PTR_ERR(args->push.s); + } + + if (inc) { + s = &args->in_sync.s; + + args->in_sync.count = inc; + *s = u_memcpya(ins, inc, sizeof(**s)); + if (IS_ERR(*s)) { + ret = PTR_ERR(*s); + goto err_free_pushs; + } + } + + if (outc) { + s = &args->out_sync.s; + + args->out_sync.count = outc; + *s = u_memcpya(outs, outc, sizeof(**s)); + if (IS_ERR(*s)) { + ret = PTR_ERR(*s); + goto err_free_ins; + } + } + + return 0; + +err_free_pushs: + u_free(args->push.s); +err_free_ins: + u_free(args->in_sync.s); + return ret; +} + +static void +nouveau_exec_ufree(struct nouveau_exec_job_args *args) +{ + u_free(args->push.s); + u_free(args->in_sync.s); + u_free(args->out_sync.s); +} + +int +nouveau_exec_ioctl_exec(struct drm_device *dev, + void __user *data, + struct drm_file *file_priv) +{ + struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); + struct nouveau_cli *cli = nouveau_cli(file_priv); + struct nouveau_abi16_chan *chan16; + struct nouveau_channel *chan = NULL; + struct nouveau_exec_job_args args = {}; + struct drm_nouveau_exec __user *req = data; + int ret = 0; + + if (unlikely(!abi16)) + return -ENOMEM; + + /* abi16 locks already */ + if (unlikely(!nouveau_cli_uvmm(cli))) + return nouveau_abi16_put(abi16, -ENOSYS); + + list_for_each_entry(chan16, &abi16->channels, head) { + if (chan16->chan->chid == req->channel) { + chan = chan16->chan; + break; + } + } + + if (!chan) + return nouveau_abi16_put(abi16, -ENOENT); + + if (unlikely(atomic_read(&chan->killed))) + return nouveau_abi16_put(abi16, -ENODEV); + + if (!chan->dma.ib_max) + return nouveau_abi16_put(abi16, -ENOSYS); + + if (unlikely(req->push_count > NOUVEAU_GEM_MAX_PUSH)) { + NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n", + req->push_count, NOUVEAU_GEM_MAX_PUSH); + return nouveau_abi16_put(abi16, -EINVAL); + } + + ret = nouveau_exec_ucopy(&args, req); + if (ret) + goto out; + + args.sched_entity = &chan16->sched_entity; + args.file_priv = file_priv; + args.chan = chan; + + ret = nouveau_exec(&args); + if (ret) + goto out_free_args; + +out_free_args: + nouveau_exec_ufree(&args); +out: + return nouveau_abi16_put(abi16, ret); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.h b/drivers/gpu/drm/nouveau/nouveau_exec.h new file mode 100644 index 000000000000..3032db27b8d7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_exec.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __NOUVEAU_EXEC_H__ +#define __NOUVEAU_EXEC_H__ + +#include + +#include "nouveau_drv.h" +#include "nouveau_sched.h" + +struct nouveau_exec_job_args { + struct drm_file *file_priv; + struct nouveau_sched_entity *sched_entity; + + struct drm_exec exec; + struct nouveau_channel *chan; + + struct { + struct drm_nouveau_sync *s; + u32 count; + } in_sync; + + struct { + struct drm_nouveau_sync *s; + u32 count; + } out_sync; + + struct { + struct drm_nouveau_exec_push *s; + u32 count; + } push; +}; + +struct nouveau_exec_job { + struct nouveau_job base; + struct nouveau_fence *fence; + struct nouveau_channel *chan; + + struct { + struct drm_nouveau_exec_push *s; + u32 count; + } push; +}; + +#define to_nouveau_exec_job(job) \ + container_of((job), struct nouveau_exec_job, base) + +int nouveau_exec_job_init(struct nouveau_exec_job **job, + struct nouveau_exec_job_args *args); + +int nouveau_exec_ioctl_exec(struct drm_device *dev, void __user *data, + struct drm_file *file_priv); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 9c8d1b911a01..f39360870c70 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -103,6 +103,7 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct device *dev = drm->dev->dev; + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); struct nouveau_vmm *vmm = nouveau_cli_vmm(cli); struct nouveau_vma *vma; int ret; @@ -110,6 +111,9 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50) return 0; + if (nvbo->no_share && uvmm && &uvmm->resv != nvbo->bo.base.resv) + return -EPERM; + ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); if (ret) return ret; @@ -120,7 +124,11 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) goto out; } - ret = nouveau_vma_new(nvbo, vmm, &vma); + /* only create a VMA on binding */ + if (!nouveau_cli_uvmm(cli)) + ret = nouveau_vma_new(nvbo, vmm, &vma); + else + ret = 0; pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); out: @@ -187,6 +195,9 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50) return; + if (nouveau_cli_uvmm(cli)) + return; + ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); if (ret) return; @@ -209,6 +220,7 @@ const struct drm_gem_object_funcs nouveau_gem_object_funcs = { .free = nouveau_gem_object_del, .open = nouveau_gem_object_open, .close = nouveau_gem_object_close, + .export = nouveau_gem_prime_export, .pin = nouveau_gem_prime_pin, .unpin = nouveau_gem_prime_unpin, .get_sg_table = nouveau_gem_prime_get_sg_table, @@ -224,18 +236,28 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, struct nouveau_bo **pnvbo) { struct nouveau_drm *drm = cli->drm; + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); + struct dma_resv *resv = NULL; struct nouveau_bo *nvbo; int ret; + if (domain & NOUVEAU_GEM_DOMAIN_NO_SHARE) { + if (unlikely(!uvmm)) + return -EINVAL; + + resv = &uvmm->resv; + } + if (!(domain & (NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART))) domain |= NOUVEAU_GEM_DOMAIN_CPU; nvbo = nouveau_bo_alloc(cli, &size, &align, domain, tile_mode, - tile_flags); + tile_flags, false); if (IS_ERR(nvbo)) return PTR_ERR(nvbo); nvbo->bo.base.funcs = &nouveau_gem_object_funcs; + nvbo->no_share = domain & NOUVEAU_GEM_DOMAIN_NO_SHARE; /* Initialize the embedded gem-object. We return a single gem-reference * to the caller, instead of a normal nouveau_bo ttm reference. */ @@ -246,7 +268,14 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, return ret; } - ret = nouveau_bo_init(nvbo, size, align, domain, NULL, NULL); + if (resv) + dma_resv_lock(resv, NULL); + + ret = nouveau_bo_init(nvbo, size, align, domain, NULL, resv); + + if (resv) + dma_resv_unlock(resv); + if (ret) return ret; @@ -279,13 +308,15 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, else rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; rep->offset = nvbo->offset; - if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { + if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50 && + !nouveau_cli_uvmm(cli)) { vma = nouveau_vma_find(nvbo, vmm); if (!vma) return -EINVAL; rep->offset = vma->addr; - } + } else + rep->offset = 0; rep->size = nvbo->bo.base.size; rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.base.vma_node); @@ -310,6 +341,11 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct nouveau_bo *nvbo = NULL; int ret = 0; + /* If uvmm wasn't initialized until now disable it completely to prevent + * userspace from mixing up UAPIs. + */ + nouveau_cli_disable_uvmm_noinit(cli); + ret = nouveau_gem_new(cli, req->info.size, req->align, req->info.domain, req->info.tile_mode, req->info.tile_flags, &nvbo); @@ -721,6 +757,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (unlikely(!abi16)) return -ENOMEM; + if (unlikely(nouveau_cli_uvmm(cli))) + return -ENOSYS; + list_for_each_entry(temp, &abi16->channels, head) { if (temp->chan->chid == req->channel) { chan = temp->chan; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h index 3b919c7c931c..10814d446435 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.h +++ b/drivers/gpu/drm/nouveau/nouveau_gem.h @@ -37,5 +37,6 @@ extern void nouveau_gem_prime_unpin(struct drm_gem_object *); extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *); extern struct drm_gem_object *nouveau_gem_prime_import_sg_table( struct drm_device *, struct dma_buf_attachment *, struct sg_table *); - +struct dma_buf *nouveau_gem_prime_export(struct drm_gem_object *gobj, + int flags); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h index 76c86d8bb01e..5365a3d3a17f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.h +++ b/drivers/gpu/drm/nouveau/nouveau_mem.h @@ -35,4 +35,9 @@ int nouveau_mem_vram(struct ttm_resource *, bool contig, u8 page); int nouveau_mem_host(struct ttm_resource *, struct ttm_tt *); void nouveau_mem_fini(struct nouveau_mem *); int nouveau_mem_map(struct nouveau_mem *, struct nvif_vmm *, struct nvif_vma *); +int +nouveau_mem_map_fixed(struct nouveau_mem *mem, + struct nvif_vmm *vmm, + u8 kind, u64 addr, + u64 offset, u64 range); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index f42c2b1b0363..1b2ff0c40fc1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -50,7 +50,7 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, dma_resv_lock(robj, NULL); nvbo = nouveau_bo_alloc(&drm->client, &size, &align, - NOUVEAU_GEM_DOMAIN_GART, 0, 0); + NOUVEAU_GEM_DOMAIN_GART, 0, 0, true); if (IS_ERR(nvbo)) { obj = ERR_CAST(nvbo); goto unlock; @@ -102,3 +102,14 @@ void nouveau_gem_prime_unpin(struct drm_gem_object *obj) nouveau_bo_unpin(nvbo); } + +struct dma_buf *nouveau_gem_prime_export(struct drm_gem_object *gobj, + int flags) +{ + struct nouveau_bo *nvbo = nouveau_gem_object(gobj); + + if (nvbo->no_share) + return ERR_PTR(-EPERM); + + return drm_gem_prime_export(gobj, flags); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c new file mode 100644 index 000000000000..b3b59fbec291 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: MIT + +#include +#include +#include + +#include "nouveau_drv.h" +#include "nouveau_gem.h" +#include "nouveau_mem.h" +#include "nouveau_dma.h" +#include "nouveau_exec.h" +#include "nouveau_abi16.h" +#include "nouveau_sched.h" + +/* FIXME + * + * We want to make sure that jobs currently executing can't be deferred by + * other jobs competing for the hardware. Otherwise we might end up with job + * timeouts just because of too many clients submitting too many jobs. We don't + * want jobs to time out because of system load, but because of the job being + * too bulky. + * + * For now allow for up to 16 concurrent jobs in flight until we know how many + * rings the hardware can process in parallel. + */ +#define NOUVEAU_SCHED_HW_SUBMISSIONS 16 +#define NOUVEAU_SCHED_JOB_TIMEOUT_MS 10000 + +int +nouveau_job_init(struct nouveau_job *job, + struct nouveau_job_args *args) +{ + struct nouveau_sched_entity *entity = args->sched_entity; + int ret; + + job->file_priv = args->file_priv; + job->cli = nouveau_cli(args->file_priv); + job->entity = entity; + + job->sync = args->sync; + job->resv_usage = args->resv_usage; + + job->ops = args->ops; + + job->in_sync.count = args->in_sync.count; + if (job->in_sync.count) { + if (job->sync) + return -EINVAL; + + job->in_sync.data = kmemdup(args->in_sync.s, + sizeof(*args->in_sync.s) * + args->in_sync.count, + GFP_KERNEL); + if (!job->in_sync.data) + return -ENOMEM; + } + + job->out_sync.count = args->out_sync.count; + if (job->out_sync.count) { + if (job->sync) { + ret = -EINVAL; + goto err_free_in_sync; + } + + job->out_sync.data = kmemdup(args->out_sync.s, + sizeof(*args->out_sync.s) * + args->out_sync.count, + GFP_KERNEL); + if (!job->out_sync.data) { + ret = -ENOMEM; + goto err_free_in_sync; + } + + job->out_sync.objs = kcalloc(job->out_sync.count, + sizeof(*job->out_sync.objs), + GFP_KERNEL); + if (!job->out_sync.objs) { + ret = -ENOMEM; + goto err_free_out_sync; + } + + job->out_sync.chains = kcalloc(job->out_sync.count, + sizeof(*job->out_sync.chains), + GFP_KERNEL); + if (!job->out_sync.chains) { + ret = -ENOMEM; + goto err_free_objs; + } + + } + + ret = drm_sched_job_init(&job->base, &entity->base, NULL); + if (ret) + goto err_free_chains; + + job->state = NOUVEAU_JOB_INITIALIZED; + + return 0; + +err_free_chains: + kfree(job->out_sync.chains); +err_free_objs: + kfree(job->out_sync.objs); +err_free_out_sync: + kfree(job->out_sync.data); +err_free_in_sync: + kfree(job->in_sync.data); +return ret; +} + +void +nouveau_job_free(struct nouveau_job *job) +{ + kfree(job->in_sync.data); + kfree(job->out_sync.data); + kfree(job->out_sync.objs); + kfree(job->out_sync.chains); +} + +void nouveau_job_fini(struct nouveau_job *job) +{ + dma_fence_put(job->done_fence); + drm_sched_job_cleanup(&job->base); + job->ops->free(job); +} + +static int +sync_find_fence(struct nouveau_job *job, + struct drm_nouveau_sync *sync, + struct dma_fence **fence) +{ + u32 stype = sync->flags & DRM_NOUVEAU_SYNC_TYPE_MASK; + u64 point = 0; + int ret; + + if (stype != DRM_NOUVEAU_SYNC_SYNCOBJ && + stype != DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ) + return -EOPNOTSUPP; + + if (stype == DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ) + point = sync->timeline_value; + + ret = drm_syncobj_find_fence(job->file_priv, + sync->handle, point, + sync->flags, fence); + if (ret) + return ret; + + return 0; +} + +static int +nouveau_job_add_deps(struct nouveau_job *job) +{ + struct dma_fence *in_fence = NULL; + int ret, i; + + for (i = 0; i < job->in_sync.count; i++) { + struct drm_nouveau_sync *sync = &job->in_sync.data[i]; + + ret = sync_find_fence(job, sync, &in_fence); + if (ret) { + NV_PRINTK(warn, job->cli, + "Failed to find syncobj (-> in): handle=%d\n", + sync->handle); + return ret; + } + + ret = drm_sched_job_add_dependency(&job->base, in_fence); + if (ret) + return ret; + } + + return 0; +} + +static void +nouveau_job_fence_attach_cleanup(struct nouveau_job *job) +{ + int i; + + for (i = 0; i < job->out_sync.count; i++) { + struct drm_syncobj *obj = job->out_sync.objs[i]; + struct dma_fence_chain *chain = job->out_sync.chains[i]; + + if (obj) + drm_syncobj_put(obj); + + if (chain) + dma_fence_chain_free(chain); + } +} + +static int +nouveau_job_fence_attach_prepare(struct nouveau_job *job) +{ + int i, ret; + + for (i = 0; i < job->out_sync.count; i++) { + struct drm_nouveau_sync *sync = &job->out_sync.data[i]; + struct drm_syncobj **pobj = &job->out_sync.objs[i]; + struct dma_fence_chain **pchain = &job->out_sync.chains[i]; + u32 stype = sync->flags & DRM_NOUVEAU_SYNC_TYPE_MASK; + + if (stype != DRM_NOUVEAU_SYNC_SYNCOBJ && + stype != DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ) { + ret = -EINVAL; + goto err_sync_cleanup; + } + + *pobj = drm_syncobj_find(job->file_priv, sync->handle); + if (!*pobj) { + NV_PRINTK(warn, job->cli, + "Failed to find syncobj (-> out): handle=%d\n", + sync->handle); + ret = -ENOENT; + goto err_sync_cleanup; + } + + if (stype == DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ) { + *pchain = dma_fence_chain_alloc(); + if (!*pchain) { + ret = -ENOMEM; + goto err_sync_cleanup; + } + } + } + + return 0; + +err_sync_cleanup: + nouveau_job_fence_attach_cleanup(job); + return ret; +} + +static void +nouveau_job_fence_attach(struct nouveau_job *job) +{ + struct dma_fence *fence = job->done_fence; + int i; + + for (i = 0; i < job->out_sync.count; i++) { + struct drm_nouveau_sync *sync = &job->out_sync.data[i]; + struct drm_syncobj **pobj = &job->out_sync.objs[i]; + struct dma_fence_chain **pchain = &job->out_sync.chains[i]; + u32 stype = sync->flags & DRM_NOUVEAU_SYNC_TYPE_MASK; + + if (stype == DRM_NOUVEAU_SYNC_TIMELINE_SYNCOBJ) { + drm_syncobj_add_point(*pobj, *pchain, fence, + sync->timeline_value); + } else { + drm_syncobj_replace_fence(*pobj, fence); + } + + drm_syncobj_put(*pobj); + *pobj = NULL; + *pchain = NULL; + } +} + +int +nouveau_job_submit(struct nouveau_job *job) +{ + struct nouveau_sched_entity *entity = to_nouveau_sched_entity(job->base.entity); + struct dma_fence *done_fence = NULL; + int ret; + + ret = nouveau_job_add_deps(job); + if (ret) + goto err; + + ret = nouveau_job_fence_attach_prepare(job); + if (ret) + goto err; + + /* Make sure the job appears on the sched_entity's queue in the same + * order as it was submitted. + */ + mutex_lock(&entity->mutex); + + /* Guarantee we won't fail after the submit() callback returned + * successfully. + */ + if (job->ops->submit) { + ret = job->ops->submit(job); + if (ret) + goto err_cleanup; + } + + drm_sched_job_arm(&job->base); + job->done_fence = dma_fence_get(&job->base.s_fence->finished); + if (job->sync) + done_fence = dma_fence_get(job->done_fence); + + if (job->ops->armed_submit) + job->ops->armed_submit(job); + + nouveau_job_fence_attach(job); + + /* Set job state before pushing the job to the scheduler, + * such that we do not overwrite the job state set in run(). + */ + job->state = NOUVEAU_JOB_SUBMIT_SUCCESS; + + drm_sched_entity_push_job(&job->base); + + mutex_unlock(&entity->mutex); + + if (done_fence) { + dma_fence_wait(done_fence, true); + dma_fence_put(done_fence); + } + + return 0; + +err_cleanup: + mutex_unlock(&entity->mutex); + nouveau_job_fence_attach_cleanup(job); +err: + job->state = NOUVEAU_JOB_SUBMIT_FAILED; + return ret; +} + +bool +nouveau_sched_entity_qwork(struct nouveau_sched_entity *entity, + struct work_struct *work) +{ + return queue_work(entity->sched_wq, work); +} + +static struct dma_fence * +nouveau_job_run(struct nouveau_job *job) +{ + struct dma_fence *fence; + + fence = job->ops->run(job); + if (IS_ERR(fence)) + job->state = NOUVEAU_JOB_RUN_FAILED; + else + job->state = NOUVEAU_JOB_RUN_SUCCESS; + + return fence; +} + +static struct dma_fence * +nouveau_sched_run_job(struct drm_sched_job *sched_job) +{ + struct nouveau_job *job = to_nouveau_job(sched_job); + + return nouveau_job_run(job); +} + +static enum drm_gpu_sched_stat +nouveau_sched_timedout_job(struct drm_sched_job *sched_job) +{ + struct nouveau_job *job = to_nouveau_job(sched_job); + + NV_PRINTK(warn, job->cli, "Job timed out.\n"); + + if (job->ops->timeout) + return job->ops->timeout(job); + + return DRM_GPU_SCHED_STAT_ENODEV; +} + +static void +nouveau_sched_free_job(struct drm_sched_job *sched_job) +{ + struct nouveau_job *job = to_nouveau_job(sched_job); + + nouveau_job_fini(job); +} + +int nouveau_sched_entity_init(struct nouveau_sched_entity *entity, + struct drm_gpu_scheduler *sched, + struct workqueue_struct *sched_wq) +{ + mutex_init(&entity->mutex); + spin_lock_init(&entity->job.list.lock); + INIT_LIST_HEAD(&entity->job.list.head); + init_waitqueue_head(&entity->job.wq); + + entity->sched_wq = sched_wq; + return drm_sched_entity_init(&entity->base, + DRM_SCHED_PRIORITY_NORMAL, + &sched, 1, NULL); +} + +void +nouveau_sched_entity_fini(struct nouveau_sched_entity *entity) +{ + drm_sched_entity_destroy(&entity->base); +} + +static const struct drm_sched_backend_ops nouveau_sched_ops = { + .run_job = nouveau_sched_run_job, + .timedout_job = nouveau_sched_timedout_job, + .free_job = nouveau_sched_free_job, +}; + +int nouveau_sched_init(struct nouveau_drm *drm) +{ + struct drm_gpu_scheduler *sched = &drm->sched; + long job_hang_limit = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); + + drm->sched_wq = create_singlethread_workqueue("nouveau_sched_wq"); + if (!drm->sched_wq) + return -ENOMEM; + + return drm_sched_init(sched, &nouveau_sched_ops, + NOUVEAU_SCHED_HW_SUBMISSIONS, 0, job_hang_limit, + NULL, NULL, "nouveau_sched", drm->dev->dev); +} + +void nouveau_sched_fini(struct nouveau_drm *drm) +{ + destroy_workqueue(drm->sched_wq); + drm_sched_fini(&drm->sched); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.h b/drivers/gpu/drm/nouveau/nouveau_sched.h new file mode 100644 index 000000000000..27ac19792597 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_sched.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef NOUVEAU_SCHED_H +#define NOUVEAU_SCHED_H + +#include + +#include +#include + +#include "nouveau_drv.h" + +#define to_nouveau_job(sched_job) \ + container_of((sched_job), struct nouveau_job, base) + +struct nouveau_job_ops; + +enum nouveau_job_state { + NOUVEAU_JOB_UNINITIALIZED = 0, + NOUVEAU_JOB_INITIALIZED, + NOUVEAU_JOB_SUBMIT_SUCCESS, + NOUVEAU_JOB_SUBMIT_FAILED, + NOUVEAU_JOB_RUN_SUCCESS, + NOUVEAU_JOB_RUN_FAILED, +}; + +struct nouveau_job_args { + struct drm_file *file_priv; + struct nouveau_sched_entity *sched_entity; + + enum dma_resv_usage resv_usage; + bool sync; + + struct { + struct drm_nouveau_sync *s; + u32 count; + } in_sync; + + struct { + struct drm_nouveau_sync *s; + u32 count; + } out_sync; + + struct nouveau_job_ops *ops; +}; + +struct nouveau_job { + struct drm_sched_job base; + + enum nouveau_job_state state; + + struct nouveau_sched_entity *entity; + + struct drm_file *file_priv; + struct nouveau_cli *cli; + + struct drm_exec exec; + enum dma_resv_usage resv_usage; + struct dma_fence *done_fence; + + bool sync; + + struct { + struct drm_nouveau_sync *data; + u32 count; + } in_sync; + + struct { + struct drm_nouveau_sync *data; + struct drm_syncobj **objs; + struct dma_fence_chain **chains; + u32 count; + } out_sync; + + struct nouveau_job_ops { + /* If .submit() returns without any error, it is guaranteed that + * armed_submit() is called. + */ + int (*submit)(struct nouveau_job *); + void (*armed_submit)(struct nouveau_job *); + struct dma_fence *(*run)(struct nouveau_job *); + void (*free)(struct nouveau_job *); + enum drm_gpu_sched_stat (*timeout)(struct nouveau_job *); + } *ops; +}; + +int nouveau_job_ucopy_syncs(struct nouveau_job_args *args, + u32 inc, u64 ins, + u32 outc, u64 outs); + +int nouveau_job_init(struct nouveau_job *job, + struct nouveau_job_args *args); +void nouveau_job_free(struct nouveau_job *job); + +int nouveau_job_submit(struct nouveau_job *job); +void nouveau_job_fini(struct nouveau_job *job); + +#define to_nouveau_sched_entity(entity) \ + container_of((entity), struct nouveau_sched_entity, base) + +struct nouveau_sched_entity { + struct drm_sched_entity base; + struct mutex mutex; + + struct workqueue_struct *sched_wq; + + struct { + struct { + struct list_head head; + spinlock_t lock; + } list; + struct wait_queue_head wq; + } job; +}; + +int nouveau_sched_entity_init(struct nouveau_sched_entity *entity, + struct drm_gpu_scheduler *sched, + struct workqueue_struct *sched_wq); +void nouveau_sched_entity_fini(struct nouveau_sched_entity *entity); + +bool nouveau_sched_entity_qwork(struct nouveau_sched_entity *entity, + struct work_struct *work); + +int nouveau_sched_init(struct nouveau_drm *drm); +void nouveau_sched_fini(struct nouveau_drm *drm); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c new file mode 100644 index 000000000000..b515a21aa08e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c @@ -0,0 +1,1921 @@ +// SPDX-License-Identifier: MIT + +/* + * Locking: + * + * The uvmm mutex protects any operations on the GPU VA space provided by the + * DRM GPU VA manager. + * + * The GEMs dma_resv lock protects the GEMs GPUVA list, hence link/unlink of a + * mapping to it's backing GEM must be performed under this lock. + * + * Actual map/unmap operations within the fence signalling critical path are + * protected by installing DMA fences to the corresponding GEMs DMA + * reservations, such that concurrent BO moves, which itself walk the GEMs GPUVA + * list in order to map/unmap it's entries, can't occur concurrently. + * + * Accessing the DRM_GPUVA_INVALIDATED flag doesn't need any separate + * protection, since there are no accesses other than from BO move callbacks + * and from the fence signalling critical path, which are already protected by + * the corresponding GEMs DMA reservation fence. + */ + +#include "nouveau_drv.h" +#include "nouveau_gem.h" +#include "nouveau_mem.h" +#include "nouveau_uvmm.h" + +#include +#include + +#include +#include +#include + +#define NOUVEAU_VA_SPACE_BITS 47 /* FIXME */ +#define NOUVEAU_VA_SPACE_START 0x0 +#define NOUVEAU_VA_SPACE_END (1ULL << NOUVEAU_VA_SPACE_BITS) + +#define list_last_op(_ops) list_last_entry(_ops, struct bind_job_op, entry) +#define list_prev_op(_op) list_prev_entry(_op, entry) +#define list_for_each_op(_op, _ops) list_for_each_entry(_op, _ops, entry) +#define list_for_each_op_from_reverse(_op, _ops) \ + list_for_each_entry_from_reverse(_op, _ops, entry) +#define list_for_each_op_safe(_op, _n, _ops) list_for_each_entry_safe(_op, _n, _ops, entry) + +enum vm_bind_op { + OP_MAP = DRM_NOUVEAU_VM_BIND_OP_MAP, + OP_UNMAP = DRM_NOUVEAU_VM_BIND_OP_UNMAP, + OP_MAP_SPARSE, + OP_UNMAP_SPARSE, +}; + +struct nouveau_uvma_prealloc { + struct nouveau_uvma *map; + struct nouveau_uvma *prev; + struct nouveau_uvma *next; +}; + +struct bind_job_op { + struct list_head entry; + + enum vm_bind_op op; + u32 flags; + + struct { + u64 addr; + u64 range; + } va; + + struct { + u32 handle; + u64 offset; + struct drm_gem_object *obj; + } gem; + + struct nouveau_uvma_region *reg; + struct nouveau_uvma_prealloc new; + struct drm_gpuva_ops *ops; +}; + +struct uvmm_map_args { + struct nouveau_uvma_region *region; + u64 addr; + u64 range; + u8 kind; +}; + +static int +nouveau_uvmm_vmm_sparse_ref(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + struct nvif_vmm *vmm = &uvmm->vmm.vmm; + + return nvif_vmm_raw_sparse(vmm, addr, range, true); +} + +static int +nouveau_uvmm_vmm_sparse_unref(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + struct nvif_vmm *vmm = &uvmm->vmm.vmm; + + return nvif_vmm_raw_sparse(vmm, addr, range, false); +} + +static int +nouveau_uvmm_vmm_get(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + struct nvif_vmm *vmm = &uvmm->vmm.vmm; + + return nvif_vmm_raw_get(vmm, addr, range, PAGE_SHIFT); +} + +static int +nouveau_uvmm_vmm_put(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + struct nvif_vmm *vmm = &uvmm->vmm.vmm; + + return nvif_vmm_raw_put(vmm, addr, range, PAGE_SHIFT); +} + +static int +nouveau_uvmm_vmm_unmap(struct nouveau_uvmm *uvmm, + u64 addr, u64 range, bool sparse) +{ + struct nvif_vmm *vmm = &uvmm->vmm.vmm; + + return nvif_vmm_raw_unmap(vmm, addr, range, PAGE_SHIFT, sparse); +} + +static int +nouveau_uvmm_vmm_map(struct nouveau_uvmm *uvmm, + u64 addr, u64 range, + u64 bo_offset, u8 kind, + struct nouveau_mem *mem) +{ + struct nvif_vmm *vmm = &uvmm->vmm.vmm; + union { + struct gf100_vmm_map_v0 gf100; + } args; + u32 argc = 0; + + switch (vmm->object.oclass) { + case NVIF_CLASS_VMM_GF100: + case NVIF_CLASS_VMM_GM200: + case NVIF_CLASS_VMM_GP100: + args.gf100.version = 0; + if (mem->mem.type & NVIF_MEM_VRAM) + args.gf100.vol = 0; + else + args.gf100.vol = 1; + args.gf100.ro = 0; + args.gf100.priv = 0; + args.gf100.kind = kind; + argc = sizeof(args.gf100); + break; + default: + WARN_ON(1); + return -ENOSYS; + } + + return nvif_vmm_raw_map(vmm, addr, range, PAGE_SHIFT, + &args, argc, + &mem->mem, bo_offset); +} + +static int +nouveau_uvma_region_sparse_unref(struct nouveau_uvma_region *reg) +{ + u64 addr = reg->va.addr; + u64 range = reg->va.range; + + return nouveau_uvmm_vmm_sparse_unref(reg->uvmm, addr, range); +} + +static int +nouveau_uvma_vmm_put(struct nouveau_uvma *uvma) +{ + u64 addr = uvma->va.va.addr; + u64 range = uvma->va.va.range; + + return nouveau_uvmm_vmm_put(uvma->uvmm, addr, range); +} + +static int +nouveau_uvma_map(struct nouveau_uvma *uvma, + struct nouveau_mem *mem) +{ + u64 addr = uvma->va.va.addr; + u64 offset = uvma->va.gem.offset; + u64 range = uvma->va.va.range; + + return nouveau_uvmm_vmm_map(uvma->uvmm, addr, range, + offset, uvma->kind, mem); +} + +static int +nouveau_uvma_unmap(struct nouveau_uvma *uvma) +{ + u64 addr = uvma->va.va.addr; + u64 range = uvma->va.va.range; + bool sparse = !!uvma->region; + + if (drm_gpuva_invalidated(&uvma->va)) + return 0; + + return nouveau_uvmm_vmm_unmap(uvma->uvmm, addr, range, sparse); +} + +static int +nouveau_uvma_alloc(struct nouveau_uvma **puvma) +{ + *puvma = kzalloc(sizeof(**puvma), GFP_KERNEL); + if (!*puvma) + return -ENOMEM; + + return 0; +} + +static void +nouveau_uvma_free(struct nouveau_uvma *uvma) +{ + kfree(uvma); +} + +static void +nouveau_uvma_gem_get(struct nouveau_uvma *uvma) +{ + drm_gem_object_get(uvma->va.gem.obj); +} + +static void +nouveau_uvma_gem_put(struct nouveau_uvma *uvma) +{ + drm_gem_object_put(uvma->va.gem.obj); +} + +static int +nouveau_uvma_region_alloc(struct nouveau_uvma_region **preg) +{ + *preg = kzalloc(sizeof(**preg), GFP_KERNEL); + if (!*preg) + return -ENOMEM; + + kref_init(&(*preg)->kref); + + return 0; +} + +static void +nouveau_uvma_region_free(struct kref *kref) +{ + struct nouveau_uvma_region *reg = + container_of(kref, struct nouveau_uvma_region, kref); + + kfree(reg); +} + +static void +nouveau_uvma_region_get(struct nouveau_uvma_region *reg) +{ + kref_get(®->kref); +} + +static void +nouveau_uvma_region_put(struct nouveau_uvma_region *reg) +{ + kref_put(®->kref, nouveau_uvma_region_free); +} + +static int +__nouveau_uvma_region_insert(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_region *reg) +{ + u64 addr = reg->va.addr; + u64 range = reg->va.range; + u64 last = addr + range - 1; + MA_STATE(mas, &uvmm->region_mt, addr, addr); + + if (unlikely(mas_walk(&mas))) { + mas_unlock(&mas); + return -EEXIST; + } + + if (unlikely(mas.last < last)) { + mas_unlock(&mas); + return -EEXIST; + } + + mas.index = addr; + mas.last = last; + + mas_store_gfp(&mas, reg, GFP_KERNEL); + + reg->uvmm = uvmm; + + return 0; +} + +static int +nouveau_uvma_region_insert(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_region *reg, + u64 addr, u64 range) +{ + int ret; + + reg->uvmm = uvmm; + reg->va.addr = addr; + reg->va.range = range; + + ret = __nouveau_uvma_region_insert(uvmm, reg); + if (ret) + return ret; + + return 0; +} + +static void +nouveau_uvma_region_remove(struct nouveau_uvma_region *reg) +{ + struct nouveau_uvmm *uvmm = reg->uvmm; + MA_STATE(mas, &uvmm->region_mt, reg->va.addr, 0); + + mas_erase(&mas); +} + +static int +nouveau_uvma_region_create(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + struct nouveau_uvma_region *reg; + int ret; + + if (!drm_gpuva_interval_empty(&uvmm->umgr, addr, range)) + return -ENOSPC; + + ret = nouveau_uvma_region_alloc(®); + if (ret) + return ret; + + ret = nouveau_uvma_region_insert(uvmm, reg, addr, range); + if (ret) + goto err_free_region; + + ret = nouveau_uvmm_vmm_sparse_ref(uvmm, addr, range); + if (ret) + goto err_region_remove; + + return 0; + +err_region_remove: + nouveau_uvma_region_remove(reg); +err_free_region: + nouveau_uvma_region_put(reg); + return ret; +} + +static struct nouveau_uvma_region * +nouveau_uvma_region_find_first(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + MA_STATE(mas, &uvmm->region_mt, addr, 0); + + return mas_find(&mas, addr + range - 1); +} + +static struct nouveau_uvma_region * +nouveau_uvma_region_find(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + struct nouveau_uvma_region *reg; + + reg = nouveau_uvma_region_find_first(uvmm, addr, range); + if (!reg) + return NULL; + + if (reg->va.addr != addr || + reg->va.range != range) + return NULL; + + return reg; +} + +static bool +nouveau_uvma_region_empty(struct nouveau_uvma_region *reg) +{ + struct nouveau_uvmm *uvmm = reg->uvmm; + + return drm_gpuva_interval_empty(&uvmm->umgr, + reg->va.addr, + reg->va.range); +} + +static int +__nouveau_uvma_region_destroy(struct nouveau_uvma_region *reg) +{ + struct nouveau_uvmm *uvmm = reg->uvmm; + u64 addr = reg->va.addr; + u64 range = reg->va.range; + + if (!nouveau_uvma_region_empty(reg)) + return -EBUSY; + + nouveau_uvma_region_remove(reg); + nouveau_uvmm_vmm_sparse_unref(uvmm, addr, range); + nouveau_uvma_region_put(reg); + + return 0; +} + +static int +nouveau_uvma_region_destroy(struct nouveau_uvmm *uvmm, + u64 addr, u64 range) +{ + struct nouveau_uvma_region *reg; + + reg = nouveau_uvma_region_find(uvmm, addr, range); + if (!reg) + return -ENOENT; + + return __nouveau_uvma_region_destroy(reg); +} + +static void +nouveau_uvma_region_dirty(struct nouveau_uvma_region *reg) +{ + + init_completion(®->complete); + reg->dirty = true; +} + +static void +nouveau_uvma_region_complete(struct nouveau_uvma_region *reg) +{ + complete_all(®->complete); +} + +static void +op_map_prepare_unwind(struct nouveau_uvma *uvma) +{ + nouveau_uvma_gem_put(uvma); + drm_gpuva_remove(&uvma->va); + nouveau_uvma_free(uvma); +} + +static void +op_unmap_prepare_unwind(struct drm_gpuva *va) +{ + drm_gpuva_insert(va->mgr, va); +} + +static void +nouveau_uvmm_sm_prepare_unwind(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops, + struct drm_gpuva_op *last, + struct uvmm_map_args *args) +{ + struct drm_gpuva_op *op = last; + u64 vmm_get_start = args ? args->addr : 0; + u64 vmm_get_end = args ? args->addr + args->range : 0; + + /* Unwind GPUVA space. */ + drm_gpuva_for_each_op_from_reverse(op, ops) { + switch (op->op) { + case DRM_GPUVA_OP_MAP: + op_map_prepare_unwind(new->map); + break; + case DRM_GPUVA_OP_REMAP: { + struct drm_gpuva_op_remap *r = &op->remap; + + if (r->next) + op_map_prepare_unwind(new->next); + + if (r->prev) + op_map_prepare_unwind(new->prev); + + op_unmap_prepare_unwind(r->unmap->va); + break; + } + case DRM_GPUVA_OP_UNMAP: + op_unmap_prepare_unwind(op->unmap.va); + break; + default: + break; + } + } + + /* Unmap operation don't allocate page tables, hence skip the following + * page table unwind. + */ + if (!args) + return; + + drm_gpuva_for_each_op(op, ops) { + switch (op->op) { + case DRM_GPUVA_OP_MAP: { + u64 vmm_get_range = vmm_get_end - vmm_get_start; + + if (vmm_get_range) + nouveau_uvmm_vmm_put(uvmm, vmm_get_start, + vmm_get_range); + break; + } + case DRM_GPUVA_OP_REMAP: { + struct drm_gpuva_op_remap *r = &op->remap; + struct drm_gpuva *va = r->unmap->va; + u64 ustart = va->va.addr; + u64 urange = va->va.range; + u64 uend = ustart + urange; + + if (r->prev) + vmm_get_start = uend; + + if (r->next) + vmm_get_end = ustart; + + if (r->prev && r->next) + vmm_get_start = vmm_get_end = 0; + + break; + } + case DRM_GPUVA_OP_UNMAP: { + struct drm_gpuva_op_unmap *u = &op->unmap; + struct drm_gpuva *va = u->va; + u64 ustart = va->va.addr; + u64 urange = va->va.range; + u64 uend = ustart + urange; + + /* Nothing to do for mappings we merge with. */ + if (uend == vmm_get_start || + ustart == vmm_get_end) + break; + + if (ustart > vmm_get_start) { + u64 vmm_get_range = ustart - vmm_get_start; + + nouveau_uvmm_vmm_put(uvmm, vmm_get_start, + vmm_get_range); + } + vmm_get_start = uend; + break; + } + default: + break; + } + + if (op == last) + break; + } +} + +static void +nouveau_uvmm_sm_map_prepare_unwind(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops, + u64 addr, u64 range) +{ + struct drm_gpuva_op *last = drm_gpuva_last_op(ops); + struct uvmm_map_args args = { + .addr = addr, + .range = range, + }; + + nouveau_uvmm_sm_prepare_unwind(uvmm, new, ops, last, &args); +} + +static void +nouveau_uvmm_sm_unmap_prepare_unwind(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops) +{ + struct drm_gpuva_op *last = drm_gpuva_last_op(ops); + + nouveau_uvmm_sm_prepare_unwind(uvmm, new, ops, last, NULL); +} + +static int +op_map_prepare(struct nouveau_uvmm *uvmm, + struct nouveau_uvma **puvma, + struct drm_gpuva_op_map *op, + struct uvmm_map_args *args) +{ + struct nouveau_uvma *uvma; + int ret; + + ret = nouveau_uvma_alloc(&uvma); + if (ret) + return ret; + + uvma->uvmm = uvmm; + uvma->region = args->region; + uvma->kind = args->kind; + + drm_gpuva_map(&uvmm->umgr, &uvma->va, op); + + /* Keep a reference until this uvma is destroyed. */ + nouveau_uvma_gem_get(uvma); + + *puvma = uvma; + return 0; +} + +static void +op_unmap_prepare(struct drm_gpuva_op_unmap *u) +{ + drm_gpuva_unmap(u); +} + +static int +nouveau_uvmm_sm_prepare(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops, + struct uvmm_map_args *args) +{ + struct drm_gpuva_op *op; + u64 vmm_get_start = args ? args->addr : 0; + u64 vmm_get_end = args ? args->addr + args->range : 0; + int ret; + + drm_gpuva_for_each_op(op, ops) { + switch (op->op) { + case DRM_GPUVA_OP_MAP: { + u64 vmm_get_range = vmm_get_end - vmm_get_start; + + ret = op_map_prepare(uvmm, &new->map, &op->map, args); + if (ret) + goto unwind; + + if (args && vmm_get_range) { + ret = nouveau_uvmm_vmm_get(uvmm, vmm_get_start, + vmm_get_range); + if (ret) { + op_map_prepare_unwind(new->map); + goto unwind; + } + } + break; + } + case DRM_GPUVA_OP_REMAP: { + struct drm_gpuva_op_remap *r = &op->remap; + struct drm_gpuva *va = r->unmap->va; + struct uvmm_map_args remap_args = { + .kind = uvma_from_va(va)->kind, + }; + u64 ustart = va->va.addr; + u64 urange = va->va.range; + u64 uend = ustart + urange; + + op_unmap_prepare(r->unmap); + + if (r->prev) { + ret = op_map_prepare(uvmm, &new->prev, r->prev, + &remap_args); + if (ret) + goto unwind; + + if (args) + vmm_get_start = uend; + } + + if (r->next) { + ret = op_map_prepare(uvmm, &new->next, r->next, + &remap_args); + if (ret) { + if (r->prev) + op_map_prepare_unwind(new->prev); + goto unwind; + } + + if (args) + vmm_get_end = ustart; + } + + if (args && (r->prev && r->next)) + vmm_get_start = vmm_get_end = 0; + + break; + } + case DRM_GPUVA_OP_UNMAP: { + struct drm_gpuva_op_unmap *u = &op->unmap; + struct drm_gpuva *va = u->va; + u64 ustart = va->va.addr; + u64 urange = va->va.range; + u64 uend = ustart + urange; + + op_unmap_prepare(u); + + if (!args) + break; + + /* Nothing to do for mappings we merge with. */ + if (uend == vmm_get_start || + ustart == vmm_get_end) + break; + + if (ustart > vmm_get_start) { + u64 vmm_get_range = ustart - vmm_get_start; + + ret = nouveau_uvmm_vmm_get(uvmm, vmm_get_start, + vmm_get_range); + if (ret) { + op_unmap_prepare_unwind(va); + goto unwind; + } + } + vmm_get_start = uend; + + break; + } + default: + ret = -EINVAL; + goto unwind; + } + } + + return 0; + +unwind: + if (op != drm_gpuva_first_op(ops)) + nouveau_uvmm_sm_prepare_unwind(uvmm, new, ops, + drm_gpuva_prev_op(op), + args); + return ret; +} + +static int +nouveau_uvmm_sm_map_prepare(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct nouveau_uvma_region *region, + struct drm_gpuva_ops *ops, + u64 addr, u64 range, u8 kind) +{ + struct uvmm_map_args args = { + .region = region, + .addr = addr, + .range = range, + .kind = kind, + }; + + return nouveau_uvmm_sm_prepare(uvmm, new, ops, &args); +} + +static int +nouveau_uvmm_sm_unmap_prepare(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops) +{ + return nouveau_uvmm_sm_prepare(uvmm, new, ops, NULL); +} + +static struct drm_gem_object * +op_gem_obj(struct drm_gpuva_op *op) +{ + switch (op->op) { + case DRM_GPUVA_OP_MAP: + return op->map.gem.obj; + case DRM_GPUVA_OP_REMAP: + /* Actually, we're looking for the GEMs backing remap.prev and + * remap.next, but since this is a remap they're identical to + * the GEM backing the unmapped GPUVA. + */ + return op->remap.unmap->va->gem.obj; + case DRM_GPUVA_OP_UNMAP: + return op->unmap.va->gem.obj; + default: + WARN(1, "Unknown operation.\n"); + return NULL; + } +} + +static void +op_map(struct nouveau_uvma *uvma) +{ + struct nouveau_bo *nvbo = nouveau_gem_object(uvma->va.gem.obj); + + nouveau_uvma_map(uvma, nouveau_mem(nvbo->bo.resource)); +} + +static void +op_unmap(struct drm_gpuva_op_unmap *u) +{ + struct drm_gpuva *va = u->va; + struct nouveau_uvma *uvma = uvma_from_va(va); + + /* nouveau_uvma_unmap() does not unmap if backing BO is evicted. */ + if (!u->keep) + nouveau_uvma_unmap(uvma); +} + +static void +op_unmap_range(struct drm_gpuva_op_unmap *u, + u64 addr, u64 range) +{ + struct nouveau_uvma *uvma = uvma_from_va(u->va); + bool sparse = !!uvma->region; + + if (!drm_gpuva_invalidated(u->va)) + nouveau_uvmm_vmm_unmap(uvma->uvmm, addr, range, sparse); +} + +static void +op_remap(struct drm_gpuva_op_remap *r, + struct nouveau_uvma_prealloc *new) +{ + struct drm_gpuva_op_unmap *u = r->unmap; + struct nouveau_uvma *uvma = uvma_from_va(u->va); + u64 addr = uvma->va.va.addr; + u64 range = uvma->va.va.range; + + if (r->prev) + addr = r->prev->va.addr + r->prev->va.range; + + if (r->next) + range = r->next->va.addr - addr; + + op_unmap_range(u, addr, range); +} + +static int +nouveau_uvmm_sm(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops) +{ + struct drm_gpuva_op *op; + + drm_gpuva_for_each_op(op, ops) { + switch (op->op) { + case DRM_GPUVA_OP_MAP: + op_map(new->map); + break; + case DRM_GPUVA_OP_REMAP: + op_remap(&op->remap, new); + break; + case DRM_GPUVA_OP_UNMAP: + op_unmap(&op->unmap); + break; + default: + break; + } + } + + return 0; +} + +static int +nouveau_uvmm_sm_map(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops) +{ + return nouveau_uvmm_sm(uvmm, new, ops); +} + +static int +nouveau_uvmm_sm_unmap(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops) +{ + return nouveau_uvmm_sm(uvmm, new, ops); +} + +static void +nouveau_uvmm_sm_cleanup(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops, bool unmap) +{ + struct drm_gpuva_op *op; + + drm_gpuva_for_each_op(op, ops) { + switch (op->op) { + case DRM_GPUVA_OP_MAP: + break; + case DRM_GPUVA_OP_REMAP: { + struct drm_gpuva_op_remap *r = &op->remap; + struct drm_gpuva_op_map *p = r->prev; + struct drm_gpuva_op_map *n = r->next; + struct drm_gpuva *va = r->unmap->va; + struct nouveau_uvma *uvma = uvma_from_va(va); + + if (unmap) { + u64 addr = va->va.addr; + u64 end = addr + va->va.range; + + if (p) + addr = p->va.addr + p->va.range; + + if (n) + end = n->va.addr; + + nouveau_uvmm_vmm_put(uvmm, addr, end - addr); + } + + nouveau_uvma_gem_put(uvma); + nouveau_uvma_free(uvma); + break; + } + case DRM_GPUVA_OP_UNMAP: { + struct drm_gpuva_op_unmap *u = &op->unmap; + struct drm_gpuva *va = u->va; + struct nouveau_uvma *uvma = uvma_from_va(va); + + if (unmap) + nouveau_uvma_vmm_put(uvma); + + nouveau_uvma_gem_put(uvma); + nouveau_uvma_free(uvma); + break; + } + default: + break; + } + } +} + +static void +nouveau_uvmm_sm_map_cleanup(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops) +{ + nouveau_uvmm_sm_cleanup(uvmm, new, ops, false); +} + +static void +nouveau_uvmm_sm_unmap_cleanup(struct nouveau_uvmm *uvmm, + struct nouveau_uvma_prealloc *new, + struct drm_gpuva_ops *ops) +{ + nouveau_uvmm_sm_cleanup(uvmm, new, ops, true); +} + +static int +nouveau_uvmm_validate_range(struct nouveau_uvmm *uvmm, u64 addr, u64 range) +{ + u64 end = addr + range; + u64 kernel_managed_end = uvmm->kernel_managed_addr + + uvmm->kernel_managed_size; + + if (addr & ~PAGE_MASK) + return -EINVAL; + + if (range & ~PAGE_MASK) + return -EINVAL; + + if (end <= addr) + return -EINVAL; + + if (addr < NOUVEAU_VA_SPACE_START || + end > NOUVEAU_VA_SPACE_END) + return -EINVAL; + + if (addr < kernel_managed_end && + end > uvmm->kernel_managed_addr) + return -EINVAL; + + return 0; +} + +static int +nouveau_uvmm_bind_job_alloc(struct nouveau_uvmm_bind_job **pjob) +{ + *pjob = kzalloc(sizeof(**pjob), GFP_KERNEL); + if (!*pjob) + return -ENOMEM; + + kref_init(&(*pjob)->kref); + + return 0; +} + +static void +nouveau_uvmm_bind_job_free(struct kref *kref) +{ + struct nouveau_uvmm_bind_job *job = + container_of(kref, struct nouveau_uvmm_bind_job, kref); + + nouveau_job_free(&job->base); + kfree(job); +} + +static void +nouveau_uvmm_bind_job_get(struct nouveau_uvmm_bind_job *job) +{ + kref_get(&job->kref); +} + +static void +nouveau_uvmm_bind_job_put(struct nouveau_uvmm_bind_job *job) +{ + kref_put(&job->kref, nouveau_uvmm_bind_job_free); +} + +static int +bind_validate_op(struct nouveau_job *job, + struct bind_job_op *op) +{ + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(job->cli); + struct drm_gem_object *obj = op->gem.obj; + + if (op->op == OP_MAP) { + if (op->gem.offset & ~PAGE_MASK) + return -EINVAL; + + if (obj->size <= op->gem.offset) + return -EINVAL; + + if (op->va.range > (obj->size - op->gem.offset)) + return -EINVAL; + } + + return nouveau_uvmm_validate_range(uvmm, op->va.addr, op->va.range); +} + +static void +bind_validate_map_sparse(struct nouveau_job *job, u64 addr, u64 range) +{ + struct nouveau_uvmm_bind_job *bind_job; + struct nouveau_sched_entity *entity = job->entity; + struct bind_job_op *op; + u64 end = addr + range; + +again: + spin_lock(&entity->job.list.lock); + list_for_each_entry(bind_job, &entity->job.list.head, entry) { + list_for_each_op(op, &bind_job->ops) { + if (op->op == OP_UNMAP) { + u64 op_addr = op->va.addr; + u64 op_end = op_addr + op->va.range; + + if (!(end <= op_addr || addr >= op_end)) { + nouveau_uvmm_bind_job_get(bind_job); + spin_unlock(&entity->job.list.lock); + wait_for_completion(&bind_job->complete); + nouveau_uvmm_bind_job_put(bind_job); + goto again; + } + } + } + } + spin_unlock(&entity->job.list.lock); +} + +static int +bind_validate_map_common(struct nouveau_job *job, u64 addr, u64 range, + bool sparse) +{ + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(job->cli); + struct nouveau_uvma_region *reg; + u64 reg_addr, reg_end; + u64 end = addr + range; + +again: + nouveau_uvmm_lock(uvmm); + reg = nouveau_uvma_region_find_first(uvmm, addr, range); + if (!reg) { + nouveau_uvmm_unlock(uvmm); + return 0; + } + + /* Generally, job submits are serialized, hence only + * dirty regions can be modified concurrently. + */ + if (reg->dirty) { + nouveau_uvma_region_get(reg); + nouveau_uvmm_unlock(uvmm); + wait_for_completion(®->complete); + nouveau_uvma_region_put(reg); + goto again; + } + nouveau_uvmm_unlock(uvmm); + + if (sparse) + return -ENOSPC; + + reg_addr = reg->va.addr; + reg_end = reg_addr + reg->va.range; + + /* Make sure the mapping is either outside of a + * region or fully enclosed by a region. + */ + if (reg_addr > addr || reg_end < end) + return -ENOSPC; + + return 0; +} + +static int +bind_validate_region(struct nouveau_job *job) +{ + struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); + struct bind_job_op *op; + int ret; + + list_for_each_op(op, &bind_job->ops) { + u64 op_addr = op->va.addr; + u64 op_range = op->va.range; + bool sparse = false; + + switch (op->op) { + case OP_MAP_SPARSE: + sparse = true; + bind_validate_map_sparse(job, op_addr, op_range); + fallthrough; + case OP_MAP: + ret = bind_validate_map_common(job, op_addr, op_range, + sparse); + if (ret) + return ret; + break; + default: + break; + } + } + + return 0; +} + +static void +bind_link_gpuvas(struct drm_gpuva_ops *ops, struct nouveau_uvma_prealloc *new) +{ + struct drm_gpuva_op *op; + + drm_gpuva_for_each_op(op, ops) { + switch (op->op) { + case DRM_GPUVA_OP_MAP: + drm_gpuva_link(&new->map->va); + break; + case DRM_GPUVA_OP_REMAP: + if (op->remap.prev) + drm_gpuva_link(&new->prev->va); + if (op->remap.next) + drm_gpuva_link(&new->next->va); + drm_gpuva_unlink(op->remap.unmap->va); + break; + case DRM_GPUVA_OP_UNMAP: + drm_gpuva_unlink(op->unmap.va); + break; + default: + break; + } + } +} + +static int +nouveau_uvmm_bind_job_submit(struct nouveau_job *job) +{ + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(job->cli); + struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); + struct nouveau_sched_entity *entity = job->entity; + struct drm_exec *exec = &job->exec; + struct bind_job_op *op; + int ret; + + list_for_each_op(op, &bind_job->ops) { + if (op->op == OP_MAP) { + op->gem.obj = drm_gem_object_lookup(job->file_priv, + op->gem.handle); + if (!op->gem.obj) + return -ENOENT; + } + + ret = bind_validate_op(job, op); + if (ret) + return ret; + } + + /* If a sparse region or mapping overlaps a dirty region, we need to + * wait for the region to complete the unbind process. This is due to + * how page table management is currently implemented. A future + * implementation might change this. + */ + ret = bind_validate_region(job); + if (ret) + return ret; + + /* Once we start modifying the GPU VA space we need to keep holding the + * uvmm lock until we can't fail anymore. This is due to the set of GPU + * VA space changes must appear atomically and we need to be able to + * unwind all GPU VA space changes on failure. + */ + nouveau_uvmm_lock(uvmm); + list_for_each_op(op, &bind_job->ops) { + switch (op->op) { + case OP_MAP_SPARSE: + ret = nouveau_uvma_region_create(uvmm, + op->va.addr, + op->va.range); + if (ret) + goto unwind_continue; + + break; + case OP_UNMAP_SPARSE: + op->reg = nouveau_uvma_region_find(uvmm, op->va.addr, + op->va.range); + if (!op->reg || op->reg->dirty) { + ret = -ENOENT; + goto unwind_continue; + } + + op->ops = drm_gpuva_sm_unmap_ops_create(&uvmm->umgr, + op->va.addr, + op->va.range); + if (IS_ERR(op->ops)) { + ret = PTR_ERR(op->ops); + goto unwind_continue; + } + + ret = nouveau_uvmm_sm_unmap_prepare(uvmm, &op->new, + op->ops); + if (ret) { + drm_gpuva_ops_free(&uvmm->umgr, op->ops); + op->ops = NULL; + op->reg = NULL; + goto unwind_continue; + } + + nouveau_uvma_region_dirty(op->reg); + + break; + case OP_MAP: { + struct nouveau_uvma_region *reg; + + reg = nouveau_uvma_region_find_first(uvmm, + op->va.addr, + op->va.range); + if (reg) { + u64 reg_addr = reg->va.addr; + u64 reg_end = reg_addr + reg->va.range; + u64 op_addr = op->va.addr; + u64 op_end = op_addr + op->va.range; + + if (unlikely(reg->dirty)) { + ret = -EINVAL; + goto unwind_continue; + } + + /* Make sure the mapping is either outside of a + * region or fully enclosed by a region. + */ + if (reg_addr > op_addr || reg_end < op_end) { + ret = -ENOSPC; + goto unwind_continue; + } + } + + op->ops = drm_gpuva_sm_map_ops_create(&uvmm->umgr, + op->va.addr, + op->va.range, + op->gem.obj, + op->gem.offset); + if (IS_ERR(op->ops)) { + ret = PTR_ERR(op->ops); + goto unwind_continue; + } + + ret = nouveau_uvmm_sm_map_prepare(uvmm, &op->new, + reg, op->ops, + op->va.addr, + op->va.range, + op->flags & 0xff); + if (ret) { + drm_gpuva_ops_free(&uvmm->umgr, op->ops); + op->ops = NULL; + goto unwind_continue; + } + + break; + } + case OP_UNMAP: + op->ops = drm_gpuva_sm_unmap_ops_create(&uvmm->umgr, + op->va.addr, + op->va.range); + if (IS_ERR(op->ops)) { + ret = PTR_ERR(op->ops); + goto unwind_continue; + } + + ret = nouveau_uvmm_sm_unmap_prepare(uvmm, &op->new, + op->ops); + if (ret) { + drm_gpuva_ops_free(&uvmm->umgr, op->ops); + op->ops = NULL; + goto unwind_continue; + } + + break; + default: + ret = -EINVAL; + goto unwind_continue; + } + } + + drm_exec_init(exec, DRM_EXEC_INTERRUPTIBLE_WAIT | + DRM_EXEC_IGNORE_DUPLICATES); + drm_exec_until_all_locked(exec) { + list_for_each_op(op, &bind_job->ops) { + struct drm_gpuva_op *va_op; + + if (IS_ERR_OR_NULL(op->ops)) + continue; + + drm_gpuva_for_each_op(va_op, op->ops) { + struct drm_gem_object *obj = op_gem_obj(va_op); + + if (unlikely(!obj)) + continue; + + ret = drm_exec_prepare_obj(exec, obj, 1); + drm_exec_retry_on_contention(exec); + if (ret) { + op = list_last_op(&bind_job->ops); + goto unwind; + } + } + } + } + + list_for_each_op(op, &bind_job->ops) { + struct drm_gpuva_op *va_op; + + if (IS_ERR_OR_NULL(op->ops)) + continue; + + drm_gpuva_for_each_op(va_op, op->ops) { + struct drm_gem_object *obj = op_gem_obj(va_op); + + if (unlikely(!obj)) + continue; + + /* Don't validate GEMs backing mappings we're about to + * unmap, it's not worth the effort. + */ + if (unlikely(va_op->op == DRM_GPUVA_OP_UNMAP)) + continue; + + ret = nouveau_bo_validate(nouveau_gem_object(obj), + true, false); + if (ret) { + op = list_last_op(&bind_job->ops); + goto unwind; + } + } + } + + /* Link and unlink GPUVAs while holding the dma_resv lock. + * + * As long as we validate() all GEMs and add fences to all GEMs DMA + * reservations backing map and remap operations we can be sure there + * won't be any concurrent (in)validations during job execution, hence + * we're safe to check drm_gpuva_invalidated() within the fence + * signalling critical path without holding a separate lock. + * + * GPUVAs about to be unmapped are safe as well, since they're unlinked + * already. + * + * GEMs from map and remap operations must be validated before linking + * their corresponding mappings to prevent the actual PT update to + * happen right away in validate() rather than asynchronously as + * intended. + * + * Note that after linking and unlinking the GPUVAs in this loop this + * function cannot fail anymore, hence there is no need for an unwind + * path. + */ + list_for_each_op(op, &bind_job->ops) { + switch (op->op) { + case OP_UNMAP_SPARSE: + case OP_MAP: + case OP_UNMAP: + bind_link_gpuvas(op->ops, &op->new); + break; + default: + break; + } + } + nouveau_uvmm_unlock(uvmm); + + spin_lock(&entity->job.list.lock); + list_add(&bind_job->entry, &entity->job.list.head); + spin_unlock(&entity->job.list.lock); + + return 0; + +unwind_continue: + op = list_prev_op(op); +unwind: + list_for_each_op_from_reverse(op, &bind_job->ops) { + switch (op->op) { + case OP_MAP_SPARSE: + nouveau_uvma_region_destroy(uvmm, op->va.addr, + op->va.range); + break; + case OP_UNMAP_SPARSE: + __nouveau_uvma_region_insert(uvmm, op->reg); + nouveau_uvmm_sm_unmap_prepare_unwind(uvmm, &op->new, + op->ops); + break; + case OP_MAP: + nouveau_uvmm_sm_map_prepare_unwind(uvmm, &op->new, + op->ops, + op->va.addr, + op->va.range); + break; + case OP_UNMAP: + nouveau_uvmm_sm_unmap_prepare_unwind(uvmm, &op->new, + op->ops); + break; + } + + drm_gpuva_ops_free(&uvmm->umgr, op->ops); + op->ops = NULL; + op->reg = NULL; + } + + nouveau_uvmm_unlock(uvmm); + drm_exec_fini(exec); + return ret; +} + +static void +nouveau_uvmm_bind_job_armed_submit(struct nouveau_job *job) +{ + struct drm_exec *exec = &job->exec; + struct drm_gem_object *obj; + unsigned long index; + + drm_exec_for_each_locked_object(exec, index, obj) + dma_resv_add_fence(obj->resv, job->done_fence, job->resv_usage); + + drm_exec_fini(exec); +} + +static struct dma_fence * +nouveau_uvmm_bind_job_run(struct nouveau_job *job) +{ + struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(job->cli); + struct bind_job_op *op; + int ret = 0; + + list_for_each_op(op, &bind_job->ops) { + switch (op->op) { + case OP_MAP_SPARSE: + /* noop */ + break; + case OP_MAP: + ret = nouveau_uvmm_sm_map(uvmm, &op->new, op->ops); + if (ret) + goto out; + break; + case OP_UNMAP_SPARSE: + fallthrough; + case OP_UNMAP: + ret = nouveau_uvmm_sm_unmap(uvmm, &op->new, op->ops); + if (ret) + goto out; + break; + } + } + +out: + if (ret) + NV_PRINTK(err, job->cli, "bind job failed: %d\n", ret); + return ERR_PTR(ret); +} + +static void +nouveau_uvmm_bind_job_free_work_fn(struct work_struct *work) +{ + struct nouveau_uvmm_bind_job *bind_job = + container_of(work, struct nouveau_uvmm_bind_job, work); + struct nouveau_job *job = &bind_job->base; + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(job->cli); + struct nouveau_sched_entity *entity = job->entity; + struct bind_job_op *op, *next; + + list_for_each_op(op, &bind_job->ops) { + struct drm_gem_object *obj = op->gem.obj; + + /* When nouveau_uvmm_bind_job_submit() fails op->ops and op->reg + * will be NULL, hence skip the cleanup. + */ + switch (op->op) { + case OP_MAP_SPARSE: + /* noop */ + break; + case OP_UNMAP_SPARSE: + if (!IS_ERR_OR_NULL(op->ops)) + nouveau_uvmm_sm_unmap_cleanup(uvmm, &op->new, + op->ops); + + if (op->reg) { + nouveau_uvma_region_sparse_unref(op->reg); + nouveau_uvmm_lock(uvmm); + nouveau_uvma_region_remove(op->reg); + nouveau_uvmm_unlock(uvmm); + nouveau_uvma_region_complete(op->reg); + nouveau_uvma_region_put(op->reg); + } + + break; + case OP_MAP: + if (!IS_ERR_OR_NULL(op->ops)) + nouveau_uvmm_sm_map_cleanup(uvmm, &op->new, + op->ops); + break; + case OP_UNMAP: + if (!IS_ERR_OR_NULL(op->ops)) + nouveau_uvmm_sm_unmap_cleanup(uvmm, &op->new, + op->ops); + break; + } + + if (!IS_ERR_OR_NULL(op->ops)) + drm_gpuva_ops_free(&uvmm->umgr, op->ops); + + if (obj) + drm_gem_object_put(obj); + } + + spin_lock(&entity->job.list.lock); + list_del(&bind_job->entry); + spin_unlock(&entity->job.list.lock); + + complete_all(&bind_job->complete); + wake_up(&entity->job.wq); + + /* Remove and free ops after removing the bind job from the job list to + * avoid races against bind_validate_map_sparse(). + */ + list_for_each_op_safe(op, next, &bind_job->ops) { + list_del(&op->entry); + kfree(op); + } + + nouveau_uvmm_bind_job_put(bind_job); +} + +static void +nouveau_uvmm_bind_job_free_qwork(struct nouveau_job *job) +{ + struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); + struct nouveau_sched_entity *entity = job->entity; + + nouveau_sched_entity_qwork(entity, &bind_job->work); +} + +static struct nouveau_job_ops nouveau_bind_job_ops = { + .submit = nouveau_uvmm_bind_job_submit, + .armed_submit = nouveau_uvmm_bind_job_armed_submit, + .run = nouveau_uvmm_bind_job_run, + .free = nouveau_uvmm_bind_job_free_qwork, +}; + +static int +bind_job_op_from_uop(struct bind_job_op **pop, + struct drm_nouveau_vm_bind_op *uop) +{ + struct bind_job_op *op; + + op = *pop = kzalloc(sizeof(*op), GFP_KERNEL); + if (!op) + return -ENOMEM; + + switch (uop->op) { + case OP_MAP: + op->op = uop->flags & DRM_NOUVEAU_VM_BIND_SPARSE ? + OP_MAP_SPARSE : OP_MAP; + break; + case OP_UNMAP: + op->op = uop->flags & DRM_NOUVEAU_VM_BIND_SPARSE ? + OP_UNMAP_SPARSE : OP_UNMAP; + break; + default: + op->op = uop->op; + break; + } + + op->flags = uop->flags; + op->va.addr = uop->addr; + op->va.range = uop->range; + op->gem.handle = uop->handle; + op->gem.offset = uop->bo_offset; + + return 0; +} + +static void +bind_job_ops_free(struct list_head *ops) +{ + struct bind_job_op *op, *next; + + list_for_each_op_safe(op, next, ops) { + list_del(&op->entry); + kfree(op); + } +} + +static int +nouveau_uvmm_bind_job_init(struct nouveau_uvmm_bind_job **pjob, + struct nouveau_uvmm_bind_job_args *__args) +{ + struct nouveau_uvmm_bind_job *job; + struct nouveau_job_args args = {}; + struct bind_job_op *op; + int i, ret; + + ret = nouveau_uvmm_bind_job_alloc(&job); + if (ret) + return ret; + + INIT_LIST_HEAD(&job->ops); + INIT_LIST_HEAD(&job->entry); + + for (i = 0; i < __args->op.count; i++) { + ret = bind_job_op_from_uop(&op, &__args->op.s[i]); + if (ret) + goto err_free; + + list_add_tail(&op->entry, &job->ops); + } + + init_completion(&job->complete); + INIT_WORK(&job->work, nouveau_uvmm_bind_job_free_work_fn); + + args.sched_entity = __args->sched_entity; + args.file_priv = __args->file_priv; + + args.in_sync.count = __args->in_sync.count; + args.in_sync.s = __args->in_sync.s; + + args.out_sync.count = __args->out_sync.count; + args.out_sync.s = __args->out_sync.s; + + args.sync = !(__args->flags & DRM_NOUVEAU_VM_BIND_RUN_ASYNC); + args.ops = &nouveau_bind_job_ops; + args.resv_usage = DMA_RESV_USAGE_BOOKKEEP; + + ret = nouveau_job_init(&job->base, &args); + if (ret) + goto err_free; + + *pjob = job; + return 0; + +err_free: + bind_job_ops_free(&job->ops); + kfree(job); + *pjob = NULL; + + return ret; +} + +int +nouveau_uvmm_ioctl_vm_init(struct drm_device *dev, + void *data, + struct drm_file *file_priv) +{ + struct nouveau_cli *cli = nouveau_cli(file_priv); + struct drm_nouveau_vm_init *init = data; + + return nouveau_uvmm_init(&cli->uvmm, cli, init->kernel_managed_addr, + init->kernel_managed_size); +} + +static int +nouveau_uvmm_vm_bind(struct nouveau_uvmm_bind_job_args *args) +{ + struct nouveau_uvmm_bind_job *job; + int ret; + + ret = nouveau_uvmm_bind_job_init(&job, args); + if (ret) + return ret; + + ret = nouveau_job_submit(&job->base); + if (ret) + goto err_job_fini; + + return 0; + +err_job_fini: + nouveau_job_fini(&job->base); + return ret; +} + +static int +nouveau_uvmm_vm_bind_ucopy(struct nouveau_uvmm_bind_job_args *args, + struct drm_nouveau_vm_bind __user *req) +{ + struct drm_nouveau_sync **s; + u32 inc = req->wait_count; + u64 ins = req->wait_ptr; + u32 outc = req->sig_count; + u64 outs = req->sig_ptr; + u32 opc = req->op_count; + u64 ops = req->op_ptr; + int ret; + + args->flags = req->flags; + + if (opc) { + args->op.count = opc; + args->op.s = u_memcpya(ops, opc, + sizeof(*args->op.s)); + if (IS_ERR(args->op.s)) + return PTR_ERR(args->op.s); + } + + if (inc) { + s = &args->in_sync.s; + + args->in_sync.count = inc; + *s = u_memcpya(ins, inc, sizeof(**s)); + if (IS_ERR(*s)) { + ret = PTR_ERR(*s); + goto err_free_ops; + } + } + + if (outc) { + s = &args->out_sync.s; + + args->out_sync.count = outc; + *s = u_memcpya(outs, outc, sizeof(**s)); + if (IS_ERR(*s)) { + ret = PTR_ERR(*s); + goto err_free_ins; + } + } + + return 0; + +err_free_ops: + u_free(args->op.s); +err_free_ins: + u_free(args->in_sync.s); + return ret; +} + +static void +nouveau_uvmm_vm_bind_ufree(struct nouveau_uvmm_bind_job_args *args) +{ + u_free(args->op.s); + u_free(args->in_sync.s); + u_free(args->out_sync.s); +} + +int +nouveau_uvmm_ioctl_vm_bind(struct drm_device *dev, + void __user *data, + struct drm_file *file_priv) +{ + struct nouveau_cli *cli = nouveau_cli(file_priv); + struct nouveau_uvmm_bind_job_args args = {}; + struct drm_nouveau_vm_bind __user *req = data; + int ret = 0; + + if (unlikely(!nouveau_cli_uvmm_locked(cli))) + return -ENOSYS; + + ret = nouveau_uvmm_vm_bind_ucopy(&args, req); + if (ret) + return ret; + + args.sched_entity = &cli->sched_entity; + args.file_priv = file_priv; + + ret = nouveau_uvmm_vm_bind(&args); + if (ret) + goto out_free_args; + +out_free_args: + nouveau_uvmm_vm_bind_ufree(&args); + return ret; +} + +void +nouveau_uvmm_bo_map_all(struct nouveau_bo *nvbo, struct nouveau_mem *mem) +{ + struct drm_gem_object *obj = &nvbo->bo.base; + struct drm_gpuva *va; + + dma_resv_assert_held(obj->resv); + + drm_gem_for_each_gpuva(va, obj) { + struct nouveau_uvma *uvma = uvma_from_va(va); + + nouveau_uvma_map(uvma, mem); + drm_gpuva_invalidate(va, false); + } +} + +void +nouveau_uvmm_bo_unmap_all(struct nouveau_bo *nvbo) +{ + struct drm_gem_object *obj = &nvbo->bo.base; + struct drm_gpuva *va; + + dma_resv_assert_held(obj->resv); + + drm_gem_for_each_gpuva(va, obj) { + struct nouveau_uvma *uvma = uvma_from_va(va); + + nouveau_uvma_unmap(uvma); + drm_gpuva_invalidate(va, true); + } +} + +int +nouveau_uvmm_init(struct nouveau_uvmm *uvmm, struct nouveau_cli *cli, + u64 kernel_managed_addr, u64 kernel_managed_size) +{ + int ret; + u64 kernel_managed_end = kernel_managed_addr + kernel_managed_size; + + mutex_init(&uvmm->mutex); + dma_resv_init(&uvmm->resv); + mt_init_flags(&uvmm->region_mt, MT_FLAGS_LOCK_EXTERN); + mt_set_external_lock(&uvmm->region_mt, &uvmm->mutex); + + mutex_lock(&cli->mutex); + + if (unlikely(cli->uvmm.disabled)) { + ret = -ENOSYS; + goto out_unlock; + } + + if (kernel_managed_end <= kernel_managed_addr) { + ret = -EINVAL; + goto out_unlock; + } + + if (kernel_managed_end > NOUVEAU_VA_SPACE_END) { + ret = -EINVAL; + goto out_unlock; + } + + uvmm->kernel_managed_addr = kernel_managed_addr; + uvmm->kernel_managed_size = kernel_managed_size; + + drm_gpuva_manager_init(&uvmm->umgr, cli->name, + NOUVEAU_VA_SPACE_START, + NOUVEAU_VA_SPACE_END, + kernel_managed_addr, kernel_managed_size, + NULL); + + ret = nvif_vmm_ctor(&cli->mmu, "uvmm", + cli->vmm.vmm.object.oclass, RAW, + kernel_managed_addr, kernel_managed_size, + NULL, 0, &cli->uvmm.vmm.vmm); + if (ret) + goto out_free_gpuva_mgr; + + cli->uvmm.vmm.cli = cli; + mutex_unlock(&cli->mutex); + + return 0; + +out_free_gpuva_mgr: + drm_gpuva_manager_destroy(&uvmm->umgr); +out_unlock: + mutex_unlock(&cli->mutex); + return ret; +} + +void +nouveau_uvmm_fini(struct nouveau_uvmm *uvmm) +{ + MA_STATE(mas, &uvmm->region_mt, 0, 0); + struct nouveau_uvma_region *reg; + struct nouveau_cli *cli = uvmm->vmm.cli; + struct nouveau_sched_entity *entity = &cli->sched_entity; + struct drm_gpuva *va, *next; + + if (!cli) + return; + + rmb(); /* for list_empty to work without lock */ + wait_event(entity->job.wq, list_empty(&entity->job.list.head)); + + nouveau_uvmm_lock(uvmm); + drm_gpuva_for_each_va_safe(va, next, &uvmm->umgr) { + struct nouveau_uvma *uvma = uvma_from_va(va); + struct drm_gem_object *obj = va->gem.obj; + + if (unlikely(va == &uvmm->umgr.kernel_alloc_node)) + continue; + + drm_gpuva_remove(va); + + dma_resv_lock(obj->resv, NULL); + drm_gpuva_unlink(va); + dma_resv_unlock(obj->resv); + + nouveau_uvma_unmap(uvma); + nouveau_uvma_vmm_put(uvma); + + nouveau_uvma_gem_put(uvma); + nouveau_uvma_free(uvma); + } + + mas_for_each(&mas, reg, ULONG_MAX) { + mas_erase(&mas); + nouveau_uvma_region_sparse_unref(reg); + nouveau_uvma_region_put(reg); + } + + WARN(!mtree_empty(&uvmm->region_mt), + "nouveau_uvma_region tree not empty, potentially leaking memory."); + __mt_destroy(&uvmm->region_mt); + nouveau_uvmm_unlock(uvmm); + + mutex_lock(&cli->mutex); + nouveau_vmm_fini(&uvmm->vmm); + drm_gpuva_manager_destroy(&uvmm->umgr); + mutex_unlock(&cli->mutex); + + dma_resv_fini(&uvmm->resv); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.h b/drivers/gpu/drm/nouveau/nouveau_uvmm.h new file mode 100644 index 000000000000..3923c03012f9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef __NOUVEAU_UVMM_H__ +#define __NOUVEAU_UVMM_H__ + +#include + +#include "nouveau_drv.h" + +struct nouveau_uvmm { + struct nouveau_vmm vmm; + struct drm_gpuva_manager umgr; + struct maple_tree region_mt; + struct mutex mutex; + struct dma_resv resv; + + u64 kernel_managed_addr; + u64 kernel_managed_size; + + bool disabled; +}; + +struct nouveau_uvma_region { + struct nouveau_uvmm *uvmm; + + struct { + u64 addr; + u64 range; + } va; + + struct kref kref; + + struct completion complete; + bool dirty; +}; + +struct nouveau_uvma { + struct drm_gpuva va; + + struct nouveau_uvmm *uvmm; + struct nouveau_uvma_region *region; + + u8 kind; +}; + +struct nouveau_uvmm_bind_job { + struct nouveau_job base; + + struct kref kref; + struct list_head entry; + struct work_struct work; + struct completion complete; + + /* struct bind_job_op */ + struct list_head ops; +}; + +struct nouveau_uvmm_bind_job_args { + struct drm_file *file_priv; + struct nouveau_sched_entity *sched_entity; + + unsigned int flags; + + struct { + struct drm_nouveau_sync *s; + u32 count; + } in_sync; + + struct { + struct drm_nouveau_sync *s; + u32 count; + } out_sync; + + struct { + struct drm_nouveau_vm_bind_op *s; + u32 count; + } op; +}; + +#define to_uvmm_bind_job(job) container_of((job), struct nouveau_uvmm_bind_job, base) + +#define uvmm_from_mgr(x) container_of((x), struct nouveau_uvmm, umgr) +#define uvma_from_va(x) container_of((x), struct nouveau_uvma, va) + +int nouveau_uvmm_init(struct nouveau_uvmm *uvmm, struct nouveau_cli *cli, + u64 kernel_managed_addr, u64 kernel_managed_size); +void nouveau_uvmm_fini(struct nouveau_uvmm *uvmm); + +void nouveau_uvmm_bo_map_all(struct nouveau_bo *nvbov, struct nouveau_mem *mem); +void nouveau_uvmm_bo_unmap_all(struct nouveau_bo *nvbo); + +int nouveau_uvmm_ioctl_vm_init(struct drm_device *dev, void __user *data, + struct drm_file *file_priv); + +int nouveau_uvmm_ioctl_vm_bind(struct drm_device *dev, void __user *data, + struct drm_file *file_priv); + +static inline void nouveau_uvmm_lock(struct nouveau_uvmm *uvmm) +{ + mutex_lock(&uvmm->mutex); +} + +static inline void nouveau_uvmm_unlock(struct nouveau_uvmm *uvmm) +{ + mutex_unlock(&uvmm->mutex); +} + +#endif From patchwork Fri Aug 4 18:23:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Danilo Krummrich X-Patchwork-Id: 131337 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp78292vqr; Fri, 4 Aug 2023 13:16:04 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGFyXW+hGvzJGeCmPeahzTcwW2v370ZdDtFd6J4UKzlvF8Ii1FP1T+x78K4k0dFzaRNzzjA X-Received: by 2002:a17:906:7490:b0:993:f744:d230 with SMTP id e16-20020a170906749000b00993f744d230mr2598465ejl.16.1691180164052; Fri, 04 Aug 2023 13:16:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691180164; cv=none; d=google.com; s=arc-20160816; b=0B4vZil8fisKV6AVrcATGYgmX/FbEWyiLaPKPL6kC//ctCR59yBJFRLMJZUy/cA3p9 7F9XZRVo1jgi+EO+VS3V47MYzXCco7wchXIkJhNtgKFRnHQoqVcuNLHoBuFosdBkc7EA 2FI2f1BBg93qwqtC45BRqQjuzCmcUdcfeBn0XDF36cT23lL2tdDgPcQC2wc6MfnNouJB Rvmz4CNC4DO3TESLhFZOgyWdWi0AEOdaPk0c910OhSt4LzUIKVZhXkbyZdzYmUIn2P8A 0Gag2wmZtuyiqKEqXGoWPhPomvYjiST/tDchlEQQq/ysjo4BXzrXidKxoY1zfYMT9PlK FGvg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Fdvxi7T0QQZA7DILvp9xTFYkELtQTf+gq8ZCaeS7cjM=; fh=K2z4qF9vBIeudG+FAsbdmtc7khu/mu2nGw/y5mnZTR0=; b=kOQYv0iXiey3fv9Oerd6DGVE//eWXyFhNOAnJuNjBB1rSiI+2RZsSh+pcyA8wm6Pk3 zsainHxiUSbd0AcDm1OODGNhaN1kuONoFpJ7SBxTGlj8WY9LN6npdwEdCAvhjl2ZYda6 Edz0ZEPuaV99XnoFkPlh7eIlFbzkKc7CFupemcI3QUA+uXCVimC3KSQbTEo3hPN3NfN5 OriHqhPkyE1aV3HJ01qcvoujNRnvgnK13QOGQKRrIrGhPh3i7gWbZ5iB2m/S3m/KLUJ1 jhu5zrpcm8PvlkYvHrUsqq2FHzqvM9gk9xY4flRbah3N69lOsVmgvj9M1JeQr1jYyBWJ eLpg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=idzdiqQs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ch7-20020a170906c2c700b009928b4e3b9csi1378202ejb.312.2023.08.04.13.15.39; Fri, 04 Aug 2023 13:16:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=idzdiqQs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231260AbjHDS1h (ORCPT + 99 others); Fri, 4 Aug 2023 14:27:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53560 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231254AbjHDS0Q (ORCPT ); Fri, 4 Aug 2023 14:26:16 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CCB5B5257 for ; Fri, 4 Aug 2023 11:25:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691173510; 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=Fdvxi7T0QQZA7DILvp9xTFYkELtQTf+gq8ZCaeS7cjM=; b=idzdiqQs2AC8sIFni7tLrjmMcBn6Le2G7J+YU7SwCHU0VvDto2vFww+hAYu+ZQ6dQjfIB4 37nJo+wBc7sKfuwyzX+jnWaHHUhAQw1izo7IArMBXGqDy66+4BETwHowSXzJLrge6hpmb/ zCEtSBx6A2ScDw5mGWHo2B7MtImxbpE= Received: from mail-lf1-f69.google.com (mail-lf1-f69.google.com [209.85.167.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-210-nQ8a8A7OPbq_00lIH1D6Ow-1; Fri, 04 Aug 2023 14:25:08 -0400 X-MC-Unique: nQ8a8A7OPbq_00lIH1D6Ow-1 Received: by mail-lf1-f69.google.com with SMTP id 2adb3069b0e04-4fe21fda5e3so2402491e87.0 for ; Fri, 04 Aug 2023 11:25:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691173507; x=1691778307; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Fdvxi7T0QQZA7DILvp9xTFYkELtQTf+gq8ZCaeS7cjM=; b=TlUXROxglvsFOvEUaXDVBJN1hBKfLNdVzC3eDTEyDNSeSYRpRBFwjnumKj+JktCW+e Z2NSk7ynGyNVPCkf1gnetxKFUhgPVWMEaryHA8iliwetXKgYpj3wumYP/91cO6D53eGV pOS/laZFWePJyZeXTqfaSefJDg8oSHrKqQZbIv/k+YUsw7r0ANfoe4GF906FXan+DWly X3VYKySXkP4/m+rgE7ufknpLs42yHDXnmJrJB/G8dqMymR68NQVEsT5bX+eP1oFf3NTK bs+G18HBJgm5ch0Mqt6/gqQ5tf3g+IYuaTy13ms8/KLELh6NmwN5lKYlgITjWlwzpvat hLVA== X-Gm-Message-State: AOJu0YyjGrq5rUW7KlEpnbrGiR4/BEtZL0m76J51XyX95q0UOl3WCfgp HaBgKHlWJXfpKIaoOk11M3fb4XBR4VBt++rmOvpAgjtkbtzPV4mYMqiJGjn8+6N86jK9Fjy4Y/m CLk20j6QmToFegBdwyFMMsJj8 X-Received: by 2002:ac2:4e8c:0:b0:4fb:7666:3bbf with SMTP id o12-20020ac24e8c000000b004fb76663bbfmr1856026lfr.26.1691173507139; Fri, 04 Aug 2023 11:25:07 -0700 (PDT) X-Received: by 2002:ac2:4e8c:0:b0:4fb:7666:3bbf with SMTP id o12-20020ac24e8c000000b004fb76663bbfmr1856008lfr.26.1691173506953; Fri, 04 Aug 2023 11:25:06 -0700 (PDT) Received: from cassiopeiae.. ([2a02:810d:4b3f:de9c:642:1aff:fe31:a19f]) by smtp.gmail.com with ESMTPSA id u15-20020a056402064f00b00523228f615dsm486979edx.88.2023.08.04.11.25.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Aug 2023 11:25:06 -0700 (PDT) From: Danilo Krummrich To: airlied@gmail.com, daniel@ffwll.ch, tzimmermann@suse.de, mripard@kernel.org, corbet@lwn.net, christian.koenig@amd.com, bskeggs@redhat.com, Liam.Howlett@oracle.com, matthew.brost@intel.com, boris.brezillon@collabora.com, alexdeucher@gmail.com, ogabbay@kernel.org, bagasdotme@gmail.com, willy@infradead.org, jason@jlekstrand.net, donald.robson@imgtec.com Cc: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich , Dave Airlie Subject: [PATCH drm-misc-next v10 12/12] drm/nouveau: debugfs: implement DRM GPU VA debugfs Date: Fri, 4 Aug 2023 20:23:52 +0200 Message-ID: <20230804182406.5222-13-dakr@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230804182406.5222-1-dakr@redhat.com> References: <20230804182406.5222-1-dakr@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773330931335664891 X-GMAIL-MSGID: 1773330931335664891 Provide the driver indirection iterating over all DRM GPU VA spaces to enable the common 'gpuvas' debugfs file for dumping DRM GPU VA spaces. Reviewed-by: Dave Airlie Signed-off-by: Danilo Krummrich --- drivers/gpu/drm/nouveau/nouveau_debugfs.c | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 99d022a91afc..053f703f2f68 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -203,6 +203,44 @@ nouveau_debugfs_pstate_open(struct inode *inode, struct file *file) return single_open(file, nouveau_debugfs_pstate_get, inode->i_private); } +static void +nouveau_debugfs_gpuva_regions(struct seq_file *m, struct nouveau_uvmm *uvmm) +{ + MA_STATE(mas, &uvmm->region_mt, 0, 0); + struct nouveau_uvma_region *reg; + + seq_puts (m, " VA regions | start | range | end \n"); + seq_puts (m, "----------------------------------------------------------------------------\n"); + mas_for_each(&mas, reg, ULONG_MAX) + seq_printf(m, " | 0x%016llx | 0x%016llx | 0x%016llx\n", + reg->va.addr, reg->va.range, reg->va.addr + reg->va.range); +} + +static int +nouveau_debugfs_gpuva(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct nouveau_drm *drm = nouveau_drm(node->minor->dev); + struct nouveau_cli *cli; + + mutex_lock(&drm->clients_lock); + list_for_each_entry(cli, &drm->clients, head) { + struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); + + if (!uvmm) + continue; + + nouveau_uvmm_lock(uvmm); + drm_debugfs_gpuva_info(m, &uvmm->umgr); + seq_puts(m, "\n"); + nouveau_debugfs_gpuva_regions(m, uvmm); + nouveau_uvmm_unlock(uvmm); + } + mutex_unlock(&drm->clients_lock); + + return 0; +} + static const struct file_operations nouveau_pstate_fops = { .owner = THIS_MODULE, .open = nouveau_debugfs_pstate_open, @@ -214,6 +252,7 @@ static const struct file_operations nouveau_pstate_fops = { static struct drm_info_list nouveau_debugfs_list[] = { { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, { "strap_peek", nouveau_debugfs_strap_peek, 0, NULL }, + DRM_DEBUGFS_GPUVA_INFO(nouveau_debugfs_gpuva, NULL), }; #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)