From cd5a44401be1eb55043a91a183d02ba8025db96e Mon Sep 17 00:00:00 2001 From: Arvind M Date: Thu, 4 Jan 2024 07:30:16 -0800 Subject: [PATCH] dla: kmd: fix race between reset and submission [1] Prior to this commit, the reset may happen in parallel with the submissions. This results in timeout during the falcon boot. [2] This commit manages the availability status to ensure that, the submissions fail gracefully when the reset is in progress. Bug 4252264 Change-Id: I499fbb742165f0584cafed00fd0c9f8a0ef47e65 Signed-off-by: Arvind M Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3046052 (cherry picked from commit ed8345cf3dd8942ef680e9c9bb63ea145dfb517b) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3182574 Reviewed-by: Ken Adams GVS: buildbot_gerritrpt Reviewed-by: Akshata Bhat --- drivers/video/tegra/host/nvdla/nvdla.c | 24 ++++++++++++++++++++++++ drivers/video/tegra/host/nvdla/nvdla.h | 7 ++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/video/tegra/host/nvdla/nvdla.c b/drivers/video/tegra/host/nvdla/nvdla.c index 269a90b5..dbc69b60 100644 --- a/drivers/video/tegra/host/nvdla/nvdla.c +++ b/drivers/video/tegra/host/nvdla/nvdla.c @@ -310,6 +310,15 @@ int nvdla_send_cmd(struct platform_device *pdev, mutex_lock(&nvdla_dev->cmd_lock); + /** + * If device is unavailable, then error out to retry after some time. + **/ + if (!nvdla_dev->available) { + nvdla_dbg_err(pdev, "Command failed: device unavailable\n"); + mutex_unlock(&nvdla_dev->cmd_lock); + return -EAGAIN; + } + /* * enable notification for command completion or error if * wait if required @@ -650,6 +659,13 @@ int nvhost_nvdla_finalize_poweron(struct platform_device *pdev) nvdla_dev->fw_version = fw_ver_read_bin; + /** + * At this point, the falcon & hardware is available to use. + **/ + mutex_lock(&nvdla_dev->cmd_lock); + nvdla_dev->available = true; + mutex_unlock(&nvdla_dev->cmd_lock); + ret = nvdla_alloc_dump_region(pdev); if (ret) { nvdla_dbg_err(pdev, "fail alloc dump region\n"); @@ -676,8 +692,16 @@ int nvhost_nvdla_prepare_poweroff(struct platform_device *pdev) { int ret; + struct nvhost_device_data *pdata = platform_get_drvdata(pdev); + struct nvdla_device *nvdla_dev = pdata->private_data; + nvdla_dbg_fn(pdev, ""); + /* Mark the device to be unavailable. */ + mutex_lock(&nvdla_dev->cmd_lock); + nvdla_dev->available = false; + mutex_unlock(&nvdla_dev->cmd_lock); + ret = nvhost_flcn_prepare_poweroff(pdev); if (ret) { nvdla_dbg_err(pdev, "failed to poweroff\n"); diff --git a/drivers/video/tegra/host/nvdla/nvdla.h b/drivers/video/tegra/host/nvdla/nvdla.h index c8139707..8886e8b7 100644 --- a/drivers/video/tegra/host/nvdla/nvdla.h +++ b/drivers/video/tegra/host/nvdla/nvdla.h @@ -1,6 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2023 NVIDIA Corporation. All rights reserved. +/* SPDX-License-Identifier: LicenseRef-NvidiaProprietary */ +/* SPDX-FileCopyrightText: Copyright (c) 2016-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * Tegra Graphics Host NVDLA */ @@ -279,6 +278,7 @@ enum nvdla_submit_mode { * @window_mem_va virtual address of window size buffer * @is_suspended flag to check if module is in suspend state. * @ping_lock lock to synchronize the ping operation requests. + * @avaiable flag to check if device is available to use. */ struct nvdla_device { struct device *dev; @@ -312,6 +312,7 @@ struct nvdla_device { bool is_suspended; #endif struct mutex ping_lock; + bool available; }; /**