diff --git a/drivers/gpu/nvgpu/common/fifo/tsg.c b/drivers/gpu/nvgpu/common/fifo/tsg.c index 31719f365..86c23c02f 100644 --- a/drivers/gpu/nvgpu/common/fifo/tsg.c +++ b/drivers/gpu/nvgpu/common/fifo/tsg.c @@ -839,6 +839,9 @@ static void nvgpu_tsg_destroy(struct nvgpu_tsg *tsg) { #ifdef CONFIG_NVGPU_CHANNEL_TSG_CONTROL nvgpu_mutex_destroy(&tsg->event_id_list_lock); +#endif +#ifdef CONFIG_NVGPU_TSG_SHARING + nvgpu_mutex_destroy(&tsg->tsg_share_lock); #endif nvgpu_mutex_destroy(&tsg->ctx_init_lock); nvgpu_mutex_destroy(&tsg->veid_alloc_lock); @@ -902,6 +905,10 @@ static void nvgpu_tsg_init_support(struct gk20a *g, u32 tsgid) nvgpu_init_list_node(&tsg->event_id_list); nvgpu_mutex_init(&tsg->event_id_list_lock); #endif +#ifdef CONFIG_NVGPU_TSG_SHARING + nvgpu_init_list_node(&tsg->ctrl_devices_list); + nvgpu_mutex_init(&tsg->tsg_share_lock); +#endif } int nvgpu_tsg_setup_sw(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/include/nvgpu/tsg.h b/drivers/gpu/nvgpu/include/nvgpu/tsg.h index 69c7d5140..4402e04e4 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/tsg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/tsg.h @@ -169,6 +169,19 @@ struct nvgpu_tsg { */ struct nvgpu_mutex event_id_list_lock; #endif + +#ifdef CONFIG_NVGPU_TSG_SHARING + /** + * List of devices sharing this TSG (Opened TSG directly or through + * share token). + */ + struct nvgpu_list_node ctrl_devices_list; + /** + * Mutex used to access/modify #ctrl_devices_list. + */ + struct nvgpu_mutex tsg_share_lock; +#endif + /** * Read write type of semaphore lock used for accessing/modifying * #ch_list, #subctx_list and #ch_list in #nvgpu_tsg_subctx. @@ -275,6 +288,13 @@ struct nvgpu_tsg { #endif }; +#ifdef CONFIG_NVGPU_TSG_SHARING +struct nvgpu_tsg_ctrl_dev_node { + u64 device_instance_id; + struct nvgpu_list_node tsg_entry; +}; +#endif + /** * @brief Allocate subcontext VEID within a TSG. * diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 429538d14..c146169d0 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c @@ -705,7 +705,7 @@ clean_up: return err; } -static int gk20a_ctrl_open_tsg(struct gk20a *g, struct nvgpu_cdev *cdev, +static int gk20a_ctrl_open_tsg(struct gk20a *g, struct gk20a_ctrl_priv *priv, struct nvgpu_gpu_open_tsg_args *args) { int err; @@ -726,7 +726,7 @@ static int gk20a_ctrl_open_tsg(struct gk20a *g, struct nvgpu_cdev *cdev, goto clean_up; } - err = nvgpu_ioctl_tsg_open(g, cdev, file); + err = nvgpu_ioctl_tsg_open(g, priv, priv->cdev, file); if (err) goto clean_up_file; @@ -2450,7 +2450,7 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg (struct nvgpu_alloc_as_args *)buf); break; case NVGPU_GPU_IOCTL_OPEN_TSG: - err = gk20a_ctrl_open_tsg(g, priv->cdev, + err = gk20a_ctrl_open_tsg(g, priv, (struct nvgpu_gpu_open_tsg_args *)buf); break; case NVGPU_GPU_IOCTL_GET_TPC_MASKS: @@ -2798,3 +2798,10 @@ void nvgpu_restore_usermode_for_poweron(struct gk20a *g) { alter_usermode_mappings(g, false); } + +#ifdef CONFIG_NVGPU_TSG_SHARING +u64 nvgpu_gpu_get_device_instance_id(struct gk20a_ctrl_priv *priv) +{ + return priv ? priv->device_instance_id : 0ULL; +} +#endif diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h index 3e1f798bf..bef7ab51e 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-2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2022, 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,6 +16,8 @@ #ifndef __NVGPU_IOCTL_CTRL_H__ #define __NVGPU_IOCTL_CTRL_H__ +struct gk20a_ctrl_priv; + 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); @@ -24,4 +26,8 @@ int gk20a_ctrl_dev_mmap(struct file *filp, struct vm_area_struct *vma); void nvgpu_hide_usermode_for_poweroff(struct gk20a *g); void nvgpu_restore_usermode_for_poweron(struct gk20a *g); +#ifdef CONFIG_NVGPU_TSG_SHARING +u64 nvgpu_gpu_get_device_instance_id(struct gk20a_ctrl_priv *priv); +#endif + #endif diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c index 8085eb359..842f86de3 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c @@ -39,6 +39,7 @@ #include #include "platform_gk20a.h" +#include "ioctl_ctrl.h" #include "ioctl_tsg.h" #include "ioctl_as.h" #include "ioctl_channel.h" @@ -50,6 +51,7 @@ struct tsg_private { struct gk20a *g; struct nvgpu_tsg *tsg; struct nvgpu_cdev *cdev; + struct gk20a_ctrl_priv *ctrl_priv; }; extern const struct file_operations gk20a_tsg_ops; @@ -450,8 +452,66 @@ static int gk20a_tsg_event_id_ctrl(struct gk20a *g, struct nvgpu_tsg *tsg, } #endif /* CONFIG_NVGPU_CHANNEL_TSG_CONTROL */ -int nvgpu_ioctl_tsg_open(struct gk20a *g, struct nvgpu_cdev *cdev, - struct file *filp) +#ifdef CONFIG_NVGPU_TSG_SHARING +static inline struct nvgpu_tsg_ctrl_dev_node * +nvgpu_tsg_ctrl_dev_node_from_tsg_entry(struct nvgpu_list_node *node) +{ + return (struct nvgpu_tsg_ctrl_dev_node *) + ((uintptr_t)node - offsetof(struct nvgpu_tsg_ctrl_dev_node, tsg_entry)); +}; + +static void nvgpu_tsg_remove_ctrl_dev_inst_id(struct nvgpu_tsg *tsg, + struct gk20a_ctrl_priv *ctrl_priv) +{ + struct nvgpu_tsg_ctrl_dev_node *node, *tmp; + struct gk20a *g = tsg->g; + + nvgpu_mutex_acquire(&tsg->tsg_share_lock); + + nvgpu_list_for_each_entry_safe(node, tmp, &tsg->ctrl_devices_list, + nvgpu_tsg_ctrl_dev_node, tsg_entry) { + if (node->device_instance_id == + nvgpu_gpu_get_device_instance_id(ctrl_priv)) { + nvgpu_log_info(g, "removing ctrl dev id %llx", + nvgpu_gpu_get_device_instance_id(ctrl_priv)); + nvgpu_list_del(&node->tsg_entry); + nvgpu_kfree(g, node); + } + } + + nvgpu_mutex_release(&tsg->tsg_share_lock); +} + +static int nvgpu_tsg_add_ctrl_dev_inst_id(struct nvgpu_tsg *tsg, + struct gk20a_ctrl_priv *ctrl_priv) +{ + struct nvgpu_tsg_ctrl_dev_node *ctrl_dev_node; + struct gk20a *g = tsg->g; + + ctrl_dev_node = (struct nvgpu_tsg_ctrl_dev_node *) nvgpu_kzalloc(g, + sizeof(struct nvgpu_tsg_ctrl_dev_node)); + if (ctrl_dev_node == NULL) { + nvgpu_err(g, "ctrl_dev_node alloc failed"); + return -ENOMEM; + } + + nvgpu_init_list_node(&ctrl_dev_node->tsg_entry); + ctrl_dev_node->device_instance_id = + nvgpu_gpu_get_device_instance_id(ctrl_priv); + + nvgpu_mutex_acquire(&tsg->tsg_share_lock); + nvgpu_list_add_tail(&ctrl_dev_node->tsg_entry, &tsg->ctrl_devices_list); + nvgpu_mutex_release(&tsg->tsg_share_lock); + + nvgpu_log_info(g, "added ctrl dev id %llx", + nvgpu_gpu_get_device_instance_id(ctrl_priv)); + + return 0; +} +#endif + +int nvgpu_ioctl_tsg_open(struct gk20a *g, struct gk20a_ctrl_priv *ctrl_priv, + struct nvgpu_cdev *cdev, struct file *filp) { struct tsg_private *priv; struct nvgpu_tsg *tsg; @@ -485,9 +545,21 @@ int nvgpu_ioctl_tsg_open(struct gk20a *g, struct nvgpu_cdev *cdev, goto free_mem; } +#ifdef CONFIG_NVGPU_TSG_SHARING + if (ctrl_priv != NULL) { + err = nvgpu_tsg_add_ctrl_dev_inst_id(tsg, ctrl_priv); + if (err != 0) { + nvgpu_err(g, "add ctrl dev failed %d", err); + nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); + goto free_mem; + } + } +#endif + priv->g = g; priv->tsg = tsg; priv->cdev = cdev; + priv->ctrl_priv = ctrl_priv; filp->private_data = priv; gk20a_sched_ctrl_tsg_added(g, tsg); @@ -518,7 +590,7 @@ int nvgpu_ioctl_tsg_dev_open(struct inode *inode, struct file *filp) return ret; } - ret = nvgpu_ioctl_tsg_open(g, cdev, filp); + ret = nvgpu_ioctl_tsg_open(g, NULL, cdev, filp); gk20a_idle(g); nvgpu_log_fn(g, "done"); @@ -548,6 +620,10 @@ int nvgpu_ioctl_tsg_dev_release(struct inode *inode, struct file *filp) tsg = priv->tsg; +#ifdef CONFIG_NVGPU_TSG_SHARING + nvgpu_tsg_remove_ctrl_dev_inst_id(tsg, priv->ctrl_priv); +#endif + nvgpu_ref_put(&tsg->refcount, nvgpu_ioctl_tsg_release); nvgpu_kfree(tsg->g, priv); return 0; diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h index c0b0f173f..341d70c77 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h +++ b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2022, 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, @@ -18,12 +18,14 @@ struct file; struct gk20a; struct nvgpu_ref; struct nvgpu_cdev; +struct gk20a_ctrl_priv; struct nvgpu_tsg *nvgpu_tsg_get_from_file(int fd); int nvgpu_ioctl_tsg_dev_release(struct inode *inode, struct file *filp); int nvgpu_ioctl_tsg_dev_open(struct inode *inode, struct file *filp); -int nvgpu_ioctl_tsg_open(struct gk20a *g, struct nvgpu_cdev *cdev, struct file *filp); +int nvgpu_ioctl_tsg_open(struct gk20a *g, struct gk20a_ctrl_priv *ctrl_priv, + struct nvgpu_cdev *cdev, struct file *filp); long nvgpu_ioctl_tsg_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); void nvgpu_ioctl_tsg_release(struct nvgpu_ref *ref);