From 1e2817e022a51466e39a3c04186c00e503ab4fb8 Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Fri, 26 Aug 2022 10:54:08 +0530 Subject: [PATCH] gpu: nvgpu: poweron for manual mode scheduling Manual mode scheduling is incompatible with Runtime PM, Added busy() and idle() calls during open/close of control-fifo nodes. Also, added functions to handle for the extra ref during SC7 suspend/resume. Jira NVGPU-8619 Signed-off-by: Debarshi Dutta Change-Id: Ic8003c90a4535c2db3aef8f8d78b9dc4a6590b1f Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2766058 Tested-by: mobile promotions Reviewed-by: mobile promotions --- drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c | 31 +++++++++++++++++++ drivers/gpu/nvgpu/include/nvgpu/nvs.h | 2 ++ drivers/gpu/nvgpu/os/linux/ioctl_nvs.c | 14 +++++++-- drivers/gpu/nvgpu/os/linux/module.c | 13 ++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c b/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c index 3bf13ef4a..7c3e92106 100644 --- a/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c +++ b/drivers/gpu/nvgpu/common/nvs/nvs_sched_ctrl.c @@ -27,6 +27,7 @@ #include #include #include +#include struct nvgpu_nvs_domain_ctrl_fifo_users { /* Flag to reserve exclusive user */ @@ -216,6 +217,36 @@ struct nvgpu_nvs_domain_ctrl_fifo *nvgpu_nvs_ctrl_fifo_create(struct gk20a *g) return sched; } +void nvgpu_nvs_ctrl_fifo_idle(struct gk20a *g) +{ + struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl = g->sched_ctrl_fifo; + + if (sched_ctrl == NULL) { + return; + } + + if (nvgpu_nvs_ctrl_fifo_is_busy(sched_ctrl)) { + gk20a_idle(g); + } +} + +void nvgpu_nvs_ctrl_fifo_unidle(struct gk20a *g) +{ + struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl = g->sched_ctrl_fifo; + int err; + + if (sched_ctrl == NULL) { + return; + } + + if (nvgpu_nvs_ctrl_fifo_is_busy(sched_ctrl)) { + err = gk20a_busy(g); + if (err != 0) { + nvgpu_err(g, "cannot busy() again!"); + } + } +} + bool nvgpu_nvs_ctrl_fifo_is_busy(struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl) { bool ret = 0; diff --git a/drivers/gpu/nvgpu/include/nvgpu/nvs.h b/drivers/gpu/nvgpu/include/nvgpu/nvs.h index c0937d2b5..f6abd3daf 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/nvs.h +++ b/drivers/gpu/nvgpu/include/nvgpu/nvs.h @@ -259,6 +259,8 @@ void nvgpu_nvs_worker_resume(struct gk20a *g); struct nvgpu_nvs_domain_ctrl_fifo *nvgpu_nvs_ctrl_fifo_create(struct gk20a *g); bool nvgpu_nvs_ctrl_fifo_user_exists(struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl, int pid, bool rw); +void nvgpu_nvs_ctrl_fifo_idle(struct gk20a *g); +void nvgpu_nvs_ctrl_fifo_unidle(struct gk20a *g); bool nvgpu_nvs_ctrl_fifo_is_busy(struct nvgpu_nvs_domain_ctrl_fifo *sched_ctrl); void nvgpu_nvs_ctrl_fifo_destroy(struct gk20a *g); bool nvgpu_nvs_ctrl_fifo_user_is_active(struct nvs_domain_ctrl_fifo_user *user); diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c b/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c index 48e996189..9a04bb580 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_nvs.c @@ -609,24 +609,34 @@ int nvgpu_nvs_ctrl_fifo_ops_open(struct inode *inode, struct file *filp) struct nvgpu_cdev *cdev; struct gk20a *g; int pid; + int err = 0; struct nvgpu_nvs_domain_ctrl_fifo_user_linux *linux_user; bool writable = filp->f_mode & FMODE_WRITE; cdev = container_of(inode->i_cdev, struct nvgpu_cdev, cdev); g = nvgpu_get_gk20a_from_cdev(cdev); + err = gk20a_busy(g); + if (err != 0) { + nvgpu_err(g, "Unable to power on the device"); + return err; + } + if (!nvgpu_is_enabled(g, NVGPU_SUPPORT_NVS_CTRL_FIFO)) { + gk20a_idle(g); return -EOPNOTSUPP; } pid = nvgpu_current_pid(g); if (nvgpu_nvs_ctrl_fifo_user_exists(g->sched_ctrl_fifo, pid, writable)) { nvgpu_err(g, "User already exists"); + gk20a_idle(g); return -EEXIST; } linux_user = nvgpu_kzalloc(g, sizeof(*linux_user)); if (linux_user == NULL) { + gk20a_idle(g); return -ENOMEM; } @@ -638,7 +648,6 @@ int nvgpu_nvs_ctrl_fifo_ops_open(struct inode *inode, struct file *filp) nvgpu_nvs_ctrl_fifo_add_user(g->sched_ctrl_fifo, &linux_user->user); filp->private_data = linux_user; - nvgpu_get(g); return 0; } @@ -660,6 +669,7 @@ int nvgpu_nvs_ctrl_fifo_ops_release(struct inode *inode, struct file *filp) if (nvgpu_nvs_ctrl_fifo_user_is_active(&linux_user->user)) { err = -EBUSY; + return err; } if (nvgpu_nvs_ctrl_fifo_is_exclusive_user(g->sched_ctrl_fifo, &linux_user->user)) { @@ -674,7 +684,7 @@ int nvgpu_nvs_ctrl_fifo_ops_release(struct inode *inode, struct file *filp) filp->private_data = NULL; nvgpu_kfree(g, linux_user); - nvgpu_put(g); + gk20a_idle(g); return err; } diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 05910e5f7..7c1c1a136 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -1429,6 +1429,11 @@ static int gk20a_pm_suspend(struct device *dev) */ nvgpu_channel_deterministic_idle(g); +#ifdef CONFIG_NVS_PRESENT + /* Release the busy() lock taken here if control-fifo is enabled */ + nvgpu_nvs_ctrl_fifo_idle(g); +#endif + /* check and wait until GPU is idle (with a timeout) */ do { nvgpu_usleep_range(1000, 1100); @@ -1467,6 +1472,10 @@ static int gk20a_pm_suspend(struct device *dev) fail_suspend: gk20a_pm_runtime_resume(dev); fail_idle: +#ifdef CONFIG_NVS_PRESENT + /* Re-Acquire the busy() lock taken here if control-fifo is enabled */ + nvgpu_nvs_ctrl_fifo_unidle(g); +#endif nvgpu_channel_deterministic_unidle(g); return ret; } @@ -1509,6 +1518,10 @@ static int gk20a_pm_resume(struct device *dev) g->suspended = false; +#ifdef CONFIG_NVS_PRESENT + /* Re-Acquire the busy() lock taken here if control-fifo is enabled */ + nvgpu_nvs_ctrl_fifo_unidle(g); +#endif nvgpu_channel_deterministic_unidle(g); return ret;