From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-lf1-f49.google.com (mail-lf1-f49.google.com [209.85.167.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E8BC23BCEE for ; Thu, 21 May 2026 15:08:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.49 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779376132; cv=none; b=YdQ2ZJHAQ9f6UG9+NuRK/GMu5bDvEFG8vhZ4a5ke6zDZeRPJCFjFUwhjhVGcjHyS/OgtNuY7rwOgP4K4YWCKfMh7feR9hjKfjJBsteWvGVqI36RNTSafh7ZMuFhXBxYQdDThjCyGMzbEzwnxOwplp58NF+0xpI+eJpvRPpP37PE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779376132; c=relaxed/simple; bh=xah8INPoIl6lNjJx8qaG+onAYm2FXP9my57l6oRqvZk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nl9gLv8WEsmFZECfkbb7jnZGiHVM92PWZ3dxpJsO0mIhXJfY+0ERVnsDfa0dGcF1UBcOZBcxf8tj6Ev2EAKWGWiHAt44Cnp8gmDGAQ8DrEUJeKv7ajHD8tuAJdB3WXNAdAv5lwq2z4uTKCMmwzoUiOu5fRvZ8NYhS3QbZJMlen4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Z2p9o7M5; arc=none smtp.client-ip=209.85.167.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Z2p9o7M5" Received: by mail-lf1-f49.google.com with SMTP id 2adb3069b0e04-5a8e33556c0so7961109e87.0 for ; Thu, 21 May 2026 08:08:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779376129; x=1779980929; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1PYTv8RRPyhzNb2k3u7IsJEhmouq09DPN/7fCUe9rJc=; b=Z2p9o7M51SOMUPueTBSphmhE21Tmen5ARXcDt1muP19oAxldj/+OSFKNn88n+iL7vc 2njzOAQL+Or0l7nFKKme8aOhxpl16mIsf6DrS3WESGo0zl0Bc64/oyUJZy042Me33uIe 88g+fNenO8q3wdt0+KP1kW3SSWaeHHIxBC7m24MqssGtp5J9Coj36WU866IXSuGy1fFA CR90yT/rh0Vi6JpVlWTRl3aVPNLNK+8bnycDgq5b2I/6R1STJv4jttW0XhicosBn+G2Z 7NZRmrIEaA6L9oLGBgBiFdHeef1h/nsAwUKEg4F+A2fbo+Im5fS588DVcg7O+RK38sPU l8vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779376129; x=1779980929; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=1PYTv8RRPyhzNb2k3u7IsJEhmouq09DPN/7fCUe9rJc=; b=FS/UjRKrMQV9JGMbu9mzjF4fAtUki3qjk0rEtIwGXUEIdXpDhs83jKFuhEdf1L2lUw zMITGg61CuYWlGtg/eP++m3lGJPcBXN+5ASNlDmAwxSwW3NSDUIHfRuWpEL71MvfgUYh dptcFnS2CtRLNDJqDwEorx7KpjA1PNykSljDoUue+B1hC1Dg4us/Mv8Y6aCzxDU/jPeD 4//zHOqMfOieRqBWM0mvfp3OV09Kket3Hn0/NsrqOW2aD5MldzL6f2i1DDJMKcONyun9 d+gj0KAredRM5UKGtXWrBYnI4L4IqY+vI6Ln21SD4EV0fWejL/UiLKA7ze83JlMlNivT ab1g== X-Forwarded-Encrypted: i=1; AFNElJ91JybHq1W4lrXEsxcaIGqLr2w9BAKdou3AYdPrYgAk5hHS/p6EpnL5EXjDYzY1vXBlmuN5ye9awC0vqL8=@vger.kernel.org X-Gm-Message-State: AOJu0Yy0yWPVJHA2e7aWbqhbRshwkFs1PD4m4Nz17MFn8d9FY4OQi9f0 lWGFE75wgkN0RBPbUin34aISA1cfWFg86jmQBuKLar6JXT5Fzj1ej52TQeY33G25go+P+LIt X-Gm-Gg: Acq92OHqpBsZ14pxhBQI86ikJbTA8yVlw5MOe3J1MIJbuaFOYxnSlXlQ6XOtTYeyCgR u2XvrHs7yNkiA0/mQvUv+pulVuwbNgakjrlN2OjKst6BfNottL4NiXlMc0NibCA3BK7PZvp/fw1 IMCxNUa1iMxEWsI/KNX1epCVBiV5RLBOLlOEV1KzlDdkMfFA8K579Yh604jb7bU2CtYNBe2tLOW kGPIzuiRx+/wgbAkjidwDbL5IY74n75dF9PXWPM861FNWo3giD1O0lJKm2D4+YPJJzotCghR3Ce 3xWdj1Fc1w5xr7ChrAqc/DP9vipq5WKkr5BCNqU+mWkHMQo71JsVfbse8XmCI6g8/3+j6JQ8t3P pI477KejLrBmqKKeegENybhujEIPD3JbN/d9KxwsTcI57rzqfwk/5a/cpfb3lfPAKqZvrBDtRlI JGegtXIIBhj5iTSKunHCKoPDN6a9iJgdoD X-Received: by 2002:a05:6512:4608:b0:5a8:837a:2a98 with SMTP id 2adb3069b0e04-5aa2ba859admr1199599e87.14.1779376128530; Thu, 21 May 2026 08:08:48 -0700 (PDT) Received: from localhost ([188.234.148.119]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5aa2f120c6esm335686e87.19.2026.05.21.08.08.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 May 2026 08:08:47 -0700 (PDT) From: Mikhail Gavrilov To: amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Cc: Alex Deucher , =?UTF-8?q?Christian=20K=C3=B6nig?= , David Airlie , Simona Vetter , Pierre-Eric Pelloux-Prayer , Sumit Semwal , linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, Mikhail Gavrilov Subject: [PATCH v5 1/2] drm/amdgpu: convert amdgpu_vm_lock_by_pasid() to drm_exec Date: Thu, 21 May 2026 20:08:39 +0500 Message-ID: <20260521150841.20625-2-mikhail.v.gavrilov@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521150841.20625-1-mikhail.v.gavrilov@gmail.com> References: <20260521104335.28978-1-mikhail.v.gavrilov@gmail.com> <20260521150841.20625-1-mikhail.v.gavrilov@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit amdgpu_vm_lock_by_pasid() looks up a VM by PASID and reserves its root PD with a bare amdgpu_bo_reserve(), returning the still-reserved root to the caller. A caller that then needs to reserve further BOs (for example the devcoredump IB dump) ends up nesting reservation_ww_class_mutex acquires without a ww_acquire_ctx, which lockdep flags as recursive locking. Convert the helper to take a drm_exec context and lock the root PD with drm_exec_lock_obj(). Callers now run it inside a drm_exec_until_all_locked() loop and can lock additional BOs in the same ww ticket, so there is no nested ww_mutex acquire. The drm_exec context holds its own reference on the locked root BO, so the helper no longer hands a root reference back to the caller: the root output parameter is dropped, and the transient reference taken across the PASID lookup is released before returning. The only existing caller, amdgpu_vm_handle_fault(), is updated accordingly. Its is_compute_context path, which previously dropped the root reservation around svm_range_restore_pages() and re-took it, now finalises the drm_exec context and re-initialises a fresh one; behaviour is otherwise unchanged. No functional change intended for the page-fault path. Reviewed-by: Christian König Signed-off-by: Mikhail Gavrilov --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 91 ++++++++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 9ba9de16a27a..d734d8c0de6e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2950,47 +2950,56 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) } /** - * amdgpu_vm_lock_by_pasid - return an amdgpu_vm and its root bo from a pasid, if possible. + * amdgpu_vm_lock_by_pasid - look up a VM by PASID and lock its root PD * @adev: amdgpu device pointer - * @root: root BO of the VM * @pasid: PASID of the VM - * The caller needs to unreserve and unref the root bo on success. + * @exec: drm_exec context to lock the root PD in + * + * Must be called from within a drm_exec_until_all_locked() loop; the caller + * runs drm_exec_retry_on_contention() afterwards. The drm_exec context holds + * a reference on the root BO until it is finalised. + * + * Return: the VM on success, or NULL if the PASID has no VM, the VM is being + * torn down, or locking the root PD failed. */ struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev, - struct amdgpu_bo **root, u32 pasid) + u32 pasid, struct drm_exec *exec) { unsigned long irqflags; + struct amdgpu_bo *root; struct amdgpu_vm *vm; int r; xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); vm = xa_load(&adev->vm_manager.pasids, pasid); - *root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL; + root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL; xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags); - if (!*root) + if (!root) return NULL; - r = amdgpu_bo_reserve(*root, true); - if (r) - goto error_unref; + r = drm_exec_lock_obj(exec, &root->tbo.base); + if (r) { + amdgpu_bo_unref(&root); + return NULL; + } /* Double check that the VM still exists */ xa_lock_irqsave(&adev->vm_manager.pasids, irqflags); vm = xa_load(&adev->vm_manager.pasids, pasid); - if (vm && vm->root.bo != *root) + if (vm && vm->root.bo != root) vm = NULL; xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags); - if (!vm) - goto error_unlock; + if (!vm) { + drm_exec_unlock_obj(exec, &root->tbo.base); + amdgpu_bo_unref(&root); + return NULL; + } - return vm; -error_unlock: - amdgpu_bo_unreserve(*root); + /* The drm_exec context holds its own reference on the root BO. */ + amdgpu_bo_unref(&root); -error_unref: - amdgpu_bo_unref(root); - return NULL; + return vm; } /** @@ -3012,33 +3021,49 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, uint64_t ts, bool write_fault) { bool is_compute_context = false; - struct amdgpu_bo *root; + struct drm_exec exec; uint64_t value, flags; struct amdgpu_vm *vm; int r; - vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid); - if (!vm) + drm_exec_init(&exec, 0, 1); + drm_exec_until_all_locked(&exec) { + vm = amdgpu_vm_lock_by_pasid(adev, pasid, &exec); + drm_exec_retry_on_contention(&exec); + if (!vm) + break; + } + if (!vm) { + drm_exec_fini(&exec); return false; + } is_compute_context = vm->is_compute_context; if (is_compute_context) { - /* Unreserve root since svm_range_restore_pages might try to reserve it. */ - /* TODO: rework svm_range_restore_pages so that this isn't necessary. */ - amdgpu_bo_unreserve(root); + /* Release the root PD lock since svm_range_restore_pages + * might try to take it. + * TODO: rework svm_range_restore_pages so that this isn't + * necessary. + */ + drm_exec_fini(&exec); if (!svm_range_restore_pages(adev, pasid, vmid, - node_id, addr >> PAGE_SHIFT, ts, write_fault)) { - amdgpu_bo_unref(&root); + node_id, addr >> PAGE_SHIFT, ts, write_fault)) return true; - } - amdgpu_bo_unref(&root); /* Re-acquire the VM lock, could be that the VM was freed in between. */ - vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid); - if (!vm) + drm_exec_init(&exec, 0, 1); + drm_exec_until_all_locked(&exec) { + vm = amdgpu_vm_lock_by_pasid(adev, pasid, &exec); + drm_exec_retry_on_contention(&exec); + if (!vm) + break; + } + if (!vm) { + drm_exec_fini(&exec); return false; + } } addr /= AMDGPU_GPU_PAGE_SIZE; @@ -3062,7 +3087,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, value = 0; } - r = dma_resv_reserve_fences(root->tbo.base.resv, 1); + r = dma_resv_reserve_fences(vm->root.bo->tbo.base.resv, 1); if (r) { pr_debug("failed %d to reserve fence slot\n", r); goto error_unlock; @@ -3076,12 +3101,10 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, r = amdgpu_vm_update_pdes(adev, vm, true); error_unlock: - amdgpu_bo_unreserve(root); + drm_exec_fini(&exec); if (r < 0) dev_err(adev->dev, "Can't handle page fault (%d)\n", r); - amdgpu_bo_unref(&root); - return false; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index d083d7aab75c..0c6e3e0368c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -593,7 +593,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, bool write_fault); struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct amdgpu_device *adev, - struct amdgpu_bo **root, u32 pasid); + u32 pasid, struct drm_exec *exec); void amdgpu_vm_set_task_info(struct amdgpu_vm *vm); -- 2.54.0