From 4dec633f5f77e17a15a5ad7da79973a8f2fa994a Mon Sep 17 00:00:00 2001 From: prsethi Date: Thu, 12 Jan 2023 17:08:22 +0000 Subject: [PATCH] gpu:nvgpu: clean the domain queues in abrupt close Domain queues are being cleaned as part of graceful close but does not gets cleaned in case of abrupt app failures. This change cleanup the queues for abrupt failures. Bug 3884011 Change-Id: I8cd07b726718b1e13a05d4455a2670cedc9dee37 Signed-off-by: prsethi Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2842632 Tested-by: mobile promotions Reviewed-by: mobile promotions --- drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c | 21 +++++ drivers/gpu/nvgpu/include/nvgpu/nvs.h | 5 +- drivers/gpu/nvgpu/os/linux/ioctl_nvs.c | 82 ++++++++++++++++++- 3 files changed, 103 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c b/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c index c70599aa0..24a7847c6 100644 --- a/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c +++ b/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c @@ -482,6 +482,27 @@ bool nvgpu_nvs_buffer_is_valid(struct gk20a *g, struct nvgpu_nvs_ctrl_queue *buf return buf->valid; } +bool nvgpu_nvs_buffer_is_sendq_valid(struct gk20a *g) +{ + struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl = g->sched_ctrl_fifo; + + return nvgpu_nvs_buffer_is_valid(g, &sched_ctrl->queues.send); +} + +bool nvgpu_nvs_buffer_is_receiveq_valid(struct gk20a *g) +{ + struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl = g->sched_ctrl_fifo; + + return nvgpu_nvs_buffer_is_valid(g, &sched_ctrl->queues.receive); +} + +bool nvgpu_nvs_buffer_is_eventq_valid(struct gk20a *g) +{ + struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl = g->sched_ctrl_fifo; + + return nvgpu_nvs_buffer_is_valid(g, &sched_ctrl->queues.event); +} + int nvgpu_nvs_buffer_alloc(struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl, size_t bytes, u8 mask, struct nvgpu_nvs_ctrl_queue *buf) { diff --git a/drivers/gpu/nvgpu/include/nvgpu/nvs.h b/drivers/gpu/nvgpu/include/nvgpu/nvs.h index cc4505713..47dfe62c5 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/nvs.h +++ b/drivers/gpu/nvgpu/include/nvgpu/nvs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -758,6 +758,9 @@ int nvgpu_nvs_ctrl_fifo_scheduler_handle_requests(struct gk20a *g); */ bool nvgpu_nvs_buffer_is_valid(struct gk20a *g, struct nvgpu_nvs_ctrl_queue *buf); +bool nvgpu_nvs_buffer_is_sendq_valid(struct gk20a *g); +bool nvgpu_nvs_buffer_is_receiveq_valid(struct gk20a *g); +bool nvgpu_nvs_buffer_is_eventq_valid(struct gk20a *g); /** * @brief Allocate DMA memory for shared queues. * diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c b/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c index 50f4541fa..f35851f23 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -662,30 +662,104 @@ int nvgpu_nvs_ctrl_fifo_ops_release(struct inode *inode, struct file *filp) { struct nvgpu_cdev *cdev; struct gk20a *g; + struct nvgpu_nvs_ctrl_queue *sendq = NULL, *recvq = NULL, *eventq = NULL; struct nvgpu_nvs_domain_ctrl_fifo_user_linux *linux_user = NULL; + enum nvgpu_nvs_ctrl_queue_num num_queue = NVGPU_NVS_INVALID; + enum nvgpu_nvs_ctrl_queue_direction queue_direction = NVGPU_NVS_DIR_INVALID; + bool is_sendq_remove = false; + bool is_eventq_remove = false; + bool is_recvq_remove = false; + bool is_exclusive_user; + u8 mask = 0; int err = 0; cdev = container_of(inode->i_cdev, struct nvgpu_cdev, cdev); g = nvgpu_get_gk20a_from_cdev(cdev); linux_user = filp->private_data; + + if (g->sched_ctrl_fifo == NULL) { + return -EINVAL; + } + if (linux_user == NULL) { return -ENODEV; } + is_exclusive_user = nvgpu_nvs_ctrl_fifo_is_exclusive_user( + g->sched_ctrl_fifo, &linux_user->user); + nvgpu_nvs_ctrl_fifo_lock_queues(g); + if (is_exclusive_user) { + num_queue = NVGPU_NVS_NUM_CONTROL; + if (nvgpu_nvs_buffer_is_sendq_valid(g)) { + queue_direction = NVGPU_NVS_DIR_CLIENT_TO_SCHEDULER; + sendq = nvgpu_nvs_ctrl_fifo_get_queue(g->sched_ctrl_fifo, + num_queue, queue_direction, &mask); + if ((sendq != NULL) && + nvgpu_nvs_ctrl_fifo_user_is_subscribed_to_queue( + &linux_user->user, sendq)) { + nvgpu_nvs_ctrl_fifo_user_unsubscribe_queue( + &linux_user->user, sendq); + is_sendq_remove = true; + } + } + if (nvgpu_nvs_buffer_is_receiveq_valid(g)) { + queue_direction = NVGPU_NVS_DIR_SCHEDULER_TO_CLIENT; + recvq = nvgpu_nvs_ctrl_fifo_get_queue(g->sched_ctrl_fifo, + num_queue, queue_direction, &mask); + if (recvq != NULL && + nvgpu_nvs_ctrl_fifo_user_is_subscribed_to_queue( + &linux_user->user, recvq)) { + nvgpu_nvs_ctrl_fifo_user_unsubscribe_queue( + &linux_user->user, recvq); + is_recvq_remove = true; + } + } + } else { + if (nvgpu_nvs_buffer_is_eventq_valid(g)) { + queue_direction = NVGPU_NVS_DIR_SCHEDULER_TO_CLIENT; + num_queue = NVGPU_NVS_NUM_EVENT; + eventq = nvgpu_nvs_ctrl_fifo_get_queue(g->sched_ctrl_fifo, + num_queue, queue_direction, &mask); + if (eventq != NULL && + nvgpu_nvs_ctrl_fifo_user_is_subscribed_to_queue( + &linux_user->user, eventq)) { + nvgpu_nvs_ctrl_fifo_user_unsubscribe_queue( + &linux_user->user, eventq); + is_eventq_remove = true; + } + } + } + if (nvgpu_nvs_ctrl_fifo_user_is_active(&linux_user->user)) { + nvgpu_err(g, "user is still active"); + nvgpu_nvs_ctrl_fifo_unlock_queues(g); err = -EBUSY; return err; } - if (nvgpu_nvs_ctrl_fifo_is_exclusive_user(g->sched_ctrl_fifo, &linux_user->user)) { - nvgpu_nvs_ctrl_fifo_reset_exclusive_user(g->sched_ctrl_fifo, &linux_user->user); + if (is_exclusive_user) { + nvgpu_nvs_ctrl_fifo_reset_exclusive_user(g->sched_ctrl_fifo, + &linux_user->user); + } + + + if (is_sendq_remove) { + nvgpu_nvs_ctrl_fifo_erase_queue_locked(g, sendq); + } + + if (is_recvq_remove) { + nvgpu_nvs_ctrl_fifo_erase_queue_locked(g, recvq); } nvgpu_nvs_ctrl_fifo_remove_user(g->sched_ctrl_fifo, &linux_user->user); + if (!nvgpu_nvs_ctrl_fifo_is_busy(g->sched_ctrl_fifo)) { - nvgpu_nvs_ctrl_fifo_erase_all_queues(g); + if (is_eventq_remove) { + nvgpu_nvs_ctrl_fifo_erase_queue_locked(g, eventq); + } } + nvgpu_nvs_ctrl_fifo_unlock_queues(g); filp->private_data = NULL;