diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 0be9c2c69..72bec2256 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c @@ -91,25 +91,6 @@ struct nvgpu_tsg_share_token_node { }; #endif -struct gk20a_ctrl_priv { - struct device *dev; - struct gk20a *g; - struct nvgpu_clk_session *clk_session; - struct nvgpu_cdev *cdev; -#ifdef CONFIG_NVGPU_TSG_SHARING - u64 device_instance_id; - u64 tsg_share_token; - struct nvgpu_list_node tsg_share_tokens_list; - struct nvgpu_mutex tokens_lock; -#endif - - struct nvgpu_list_node list; - struct { - struct vm_area_struct *vma; - bool vma_mapped; - } usermode_vma; -}; - static inline struct gk20a_ctrl_priv * gk20a_ctrl_priv_from_list(struct nvgpu_list_node *node) { @@ -178,6 +159,8 @@ int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp) nvgpu_mutex_init(&priv->tokens_lock); #endif + nvgpu_ref_init(&priv->refcount); + if (!g->sw_ready) { err = gk20a_busy(g); if (err) @@ -202,9 +185,9 @@ free_ref: return err; } -int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp) +void nvgpu_ioctl_ctrl_release(struct nvgpu_ref *ref) { - struct gk20a_ctrl_priv *priv = filp->private_data; + struct gk20a_ctrl_priv *priv = container_of(ref, struct gk20a_ctrl_priv, refcount); struct gk20a *g = priv->g; struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); @@ -219,6 +202,16 @@ int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp) nvgpu_put(g); nvgpu_kfree(g, priv); +} + +int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp) +{ + struct gk20a_ctrl_priv *priv = filp->private_data; + struct gk20a *g = priv->g; + + nvgpu_log_fn(g, " "); + + nvgpu_ref_put(&priv->refcount, nvgpu_ioctl_ctrl_release); return 0; } diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h index e370c472c..177be513a 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-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, @@ -16,9 +16,36 @@ #ifndef __NVGPU_IOCTL_CTRL_H__ #define __NVGPU_IOCTL_CTRL_H__ -struct gk20a_ctrl_priv; struct nvgpu_tsg; +struct gk20a_ctrl_priv { + struct device *dev; + struct gk20a *g; + struct nvgpu_clk_session *clk_session; + struct nvgpu_cdev *cdev; +#ifdef CONFIG_NVGPU_TSG_SHARING + u64 device_instance_id; + u64 tsg_share_token; + struct nvgpu_list_node tsg_share_tokens_list; + struct nvgpu_mutex tokens_lock; +#endif + + /** + * This ref is initialized during gk20a_ctrl_dev_open. + * This is ref_get whenever a TSG is opened for a device. + * This is ref_put whenever a TSG is released from a device. + */ + struct nvgpu_ref refcount; + + struct nvgpu_list_node list; + struct { + struct vm_area_struct *vma; + bool vma_mapped; + } usermode_vma; +}; + +void nvgpu_ioctl_ctrl_release(struct nvgpu_ref *ref); + int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp); int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp); long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c index 70f281e2d..d3fe2ba6a 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c @@ -696,7 +696,12 @@ int nvgpu_ioctl_tsg_open(struct gk20a *g, struct gk20a_ctrl_priv *ctrl_priv, priv->g = g; priv->tsg = tsg; priv->cdev = cdev; + + if (ctrl_priv != NULL) { + nvgpu_ref_get(&ctrl_priv->refcount); + } priv->ctrl_priv = ctrl_priv; + filp->private_data = priv; return 0; @@ -766,25 +771,30 @@ int nvgpu_ioctl_tsg_dev_release(struct inode *inode, struct file *filp) g = tsg->g; #ifdef CONFIG_NVGPU_TSG_SHARING - nvgpu_mutex_acquire(&tsg->tsg_share_lock); + if (priv->ctrl_priv) { + nvgpu_mutex_acquire(&tsg->tsg_share_lock); - err = nvgpu_gpu_tsg_revoke_share_tokens(g, - nvgpu_gpu_get_device_instance_id(priv->ctrl_priv), - tsg, &count); - if (err != 0) { - nvgpu_err(g, "revoke token(%llu) failed %d", - nvgpu_gpu_get_device_instance_id(priv->ctrl_priv), - err); + err = nvgpu_gpu_tsg_revoke_share_tokens(g, + nvgpu_gpu_get_device_instance_id(priv->ctrl_priv), + tsg, &count); + if (err != 0) { + nvgpu_err(g, "revoke token(%llu) failed %d", + nvgpu_gpu_get_device_instance_id(priv->ctrl_priv), + err); + } + + tsg->share_token_count -= count; + + nvgpu_mutex_release(&tsg->tsg_share_lock); + + nvgpu_tsg_remove_ctrl_dev_inst_id(tsg, priv->ctrl_priv); } - - tsg->share_token_count -= count; - - nvgpu_mutex_release(&tsg->tsg_share_lock); - - nvgpu_tsg_remove_ctrl_dev_inst_id(tsg, priv->ctrl_priv); #endif nvgpu_ref_put(&tsg->refcount, nvgpu_ioctl_tsg_release); + if (priv->ctrl_priv) { + nvgpu_ref_put(&priv->ctrl_priv->refcount, nvgpu_ioctl_ctrl_release); + } nvgpu_kfree(g, priv); nvgpu_put(g);