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 <prsethi@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2842632
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
prsethi
2023-01-12 17:08:22 +00:00
committed by mobile promotions
parent 04cd344b35
commit 4dec633f5f
3 changed files with 103 additions and 5 deletions

View File

@@ -482,6 +482,27 @@ bool nvgpu_nvs_buffer_is_valid(struct gk20a *g, struct nvgpu_nvs_ctrl_queue *buf
return buf->valid; 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, int nvgpu_nvs_buffer_alloc(struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl,
size_t bytes, u8 mask, struct nvgpu_nvs_ctrl_queue *buf) size_t bytes, u8 mask, struct nvgpu_nvs_ctrl_queue *buf)
{ {

View File

@@ -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 * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * 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_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. * @brief Allocate DMA memory for shared queues.
* *

View File

@@ -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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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 nvgpu_cdev *cdev;
struct gk20a *g; 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; 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; int err = 0;
cdev = container_of(inode->i_cdev, struct nvgpu_cdev, cdev); cdev = container_of(inode->i_cdev, struct nvgpu_cdev, cdev);
g = nvgpu_get_gk20a_from_cdev(cdev); g = nvgpu_get_gk20a_from_cdev(cdev);
linux_user = filp->private_data; linux_user = filp->private_data;
if (g->sched_ctrl_fifo == NULL) {
return -EINVAL;
}
if (linux_user == NULL) { if (linux_user == NULL) {
return -ENODEV; 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)) { 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; err = -EBUSY;
return err; return err;
} }
if (nvgpu_nvs_ctrl_fifo_is_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); 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); nvgpu_nvs_ctrl_fifo_remove_user(g->sched_ctrl_fifo, &linux_user->user);
if (!nvgpu_nvs_ctrl_fifo_is_busy(g->sched_ctrl_fifo)) { 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; filp->private_data = NULL;