mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: domains as files for access control
Create device nodes for user-created scheduling domains. This helps leverage filesystem based access control: domains can be chosen to be available for a limited set of users on a system. The device nodes are dynamic: they can be removed while the driver is running normally. This is a bit different from the nodes that exist until the driver is unloaded, so the devno/domain mapping is stored in a separate list. The usual container_of pattern would suffer from an unavoidable race condition if a domain file was opened while the same domain would get removed. As usual, domain refcounting prevents a domain from being removed. Now the open device files hold refs and thus any open domain files prevent a domain from getting removed, in addition to the userspace-invisible ref that is taken when a TSG is bound to a domain. While at it, make the query ioctl guarded by the sched domain mutex, as domains might technically get added or removed during the querying code. Jira NVGPU-6788 Change-Id: Ief2a09a442c4e70f1f2be8a32359341071d74659 Signed-off-by: Konsta Hölttä <kholtta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2651164 Reviewed-by: Alex Waterman <alexw@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
mobile promotions
parent
beed6d3c2b
commit
3a64fdefc4
@@ -344,6 +344,8 @@ nvgpu_nvs_domain_by_id_locked(struct gk20a *g, u64 domain_id)
|
|||||||
struct nvgpu_nvs_scheduler *sched = g->scheduler;
|
struct nvgpu_nvs_scheduler *sched = g->scheduler;
|
||||||
struct nvs_domain *nvs_dom;
|
struct nvs_domain *nvs_dom;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_nvs, "lookup %llu", domain_id);
|
||||||
|
|
||||||
nvs_domain_for_each(sched->sched, nvs_dom) {
|
nvs_domain_for_each(sched->sched, nvs_dom) {
|
||||||
struct nvgpu_nvs_domain *nvgpu_dom = nvs_dom->priv;
|
struct nvgpu_nvs_domain *nvgpu_dom = nvs_dom->priv;
|
||||||
|
|
||||||
@@ -360,6 +362,8 @@ nvgpu_nvs_domain_by_id(struct gk20a *g, u64 domain_id)
|
|||||||
{
|
{
|
||||||
struct nvgpu_nvs_domain *dom = NULL;
|
struct nvgpu_nvs_domain *dom = NULL;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_nvs, "lookup %llu", domain_id);
|
||||||
|
|
||||||
nvgpu_mutex_acquire(&g->sched_mutex);
|
nvgpu_mutex_acquire(&g->sched_mutex);
|
||||||
|
|
||||||
dom = nvgpu_nvs_domain_by_id_locked(g, domain_id);
|
dom = nvgpu_nvs_domain_by_id_locked(g, domain_id);
|
||||||
@@ -381,6 +385,8 @@ nvgpu_nvs_domain_by_name(struct gk20a *g, const char *name)
|
|||||||
struct nvgpu_nvs_domain *dom = NULL;
|
struct nvgpu_nvs_domain *dom = NULL;
|
||||||
struct nvgpu_nvs_scheduler *sched = g->scheduler;
|
struct nvgpu_nvs_scheduler *sched = g->scheduler;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_nvs, "lookup %s", name);
|
||||||
|
|
||||||
nvgpu_mutex_acquire(&g->sched_mutex);
|
nvgpu_mutex_acquire(&g->sched_mutex);
|
||||||
|
|
||||||
nvs_dom = nvs_domain_by_name(sched->sched, name);
|
nvs_dom = nvs_domain_by_name(sched->sched, name);
|
||||||
@@ -396,11 +402,23 @@ unlock:
|
|||||||
return dom;
|
return dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvs_domain_get(struct gk20a *g, struct nvgpu_nvs_domain *dom)
|
||||||
|
{
|
||||||
|
nvgpu_mutex_acquire(&g->sched_mutex);
|
||||||
|
WARN_ON(dom->ref == 0U);
|
||||||
|
dom->ref++;
|
||||||
|
nvgpu_log(g, gpu_dbg_nvs, "domain %s: ref++ = %u",
|
||||||
|
dom->parent->name, dom->ref);
|
||||||
|
nvgpu_mutex_release(&g->sched_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
void nvgpu_nvs_domain_put(struct gk20a *g, struct nvgpu_nvs_domain *dom)
|
void nvgpu_nvs_domain_put(struct gk20a *g, struct nvgpu_nvs_domain *dom)
|
||||||
{
|
{
|
||||||
nvgpu_mutex_acquire(&g->sched_mutex);
|
nvgpu_mutex_acquire(&g->sched_mutex);
|
||||||
dom->ref--;
|
dom->ref--;
|
||||||
WARN_ON(dom->ref == 0U);
|
WARN_ON(dom->ref == 0U);
|
||||||
|
nvgpu_log(g, gpu_dbg_nvs, "domain %s: ref-- = %u",
|
||||||
|
dom->parent->name, dom->ref);
|
||||||
nvgpu_mutex_release(&g->sched_mutex);
|
nvgpu_mutex_release(&g->sched_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#define NVS_LOG_BUF_SIZE 128
|
#define NVS_LOG_BUF_SIZE 128
|
||||||
|
|
||||||
struct gk20a;
|
struct gk20a;
|
||||||
|
struct nvgpu_nvs_domain_ioctl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NvGPU KMD domain implementation details for nvsched.
|
* NvGPU KMD domain implementation details for nvsched.
|
||||||
@@ -65,6 +66,11 @@ struct nvgpu_nvs_domain {
|
|||||||
* ioctl layer and a TSG putting a ref does not result in domain deletion.
|
* ioctl layer and a TSG putting a ref does not result in domain deletion.
|
||||||
*/
|
*/
|
||||||
u32 ref;
|
u32 ref;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace API on the device nodes.
|
||||||
|
*/
|
||||||
|
struct nvgpu_nvs_domain_ioctl *ioctl;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nvgpu_nvs_worker {
|
struct nvgpu_nvs_worker {
|
||||||
@@ -95,6 +101,7 @@ struct nvgpu_nvs_domain *
|
|||||||
nvgpu_nvs_domain_by_id(struct gk20a *g, u64 domain_id);
|
nvgpu_nvs_domain_by_id(struct gk20a *g, u64 domain_id);
|
||||||
struct nvgpu_nvs_domain *
|
struct nvgpu_nvs_domain *
|
||||||
nvgpu_nvs_domain_by_name(struct gk20a *g, const char *name);
|
nvgpu_nvs_domain_by_name(struct gk20a *g, const char *name);
|
||||||
|
void nvgpu_nvs_domain_get(struct gk20a *g, struct nvgpu_nvs_domain *dom);
|
||||||
void nvgpu_nvs_domain_put(struct gk20a *g, struct nvgpu_nvs_domain *dom);
|
void nvgpu_nvs_domain_put(struct gk20a *g, struct nvgpu_nvs_domain *dom);
|
||||||
/*
|
/*
|
||||||
* Debug wrapper for NVS code.
|
* Debug wrapper for NVS code.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2021-2022, 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,
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <linux/cdev.h>
|
#include <linux/cdev.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/file.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
#include <uapi/linux/nvgpu-nvs.h>
|
#include <uapi/linux/nvgpu-nvs.h>
|
||||||
@@ -20,12 +21,64 @@
|
|||||||
#include <nvgpu/nvs.h>
|
#include <nvgpu/nvs.h>
|
||||||
#include <nvgpu/gk20a.h>
|
#include <nvgpu/gk20a.h>
|
||||||
#include <nvgpu/nvgpu_init.h>
|
#include <nvgpu/nvgpu_init.h>
|
||||||
|
#include "os_linux.h"
|
||||||
|
|
||||||
#include <nvs/sched.h>
|
#include <nvs/sched.h>
|
||||||
#include <nvs/domain.h>
|
#include <nvs/domain.h>
|
||||||
|
|
||||||
#include "ioctl.h"
|
#include "ioctl.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OS-specific layer to hold device node mapping for a domain.
|
||||||
|
*/
|
||||||
|
struct nvgpu_nvs_domain_ioctl {
|
||||||
|
struct gk20a *g;
|
||||||
|
struct nvgpu_nvs_domain *domain;
|
||||||
|
struct cdev *cdev;
|
||||||
|
struct device *dev;
|
||||||
|
struct nvgpu_class *class;
|
||||||
|
struct list_head list; /* entry in cdev_lookup_list */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This lock serializes domain removal and opening of domain device nodes.
|
||||||
|
*/
|
||||||
|
static DEFINE_MUTEX(cdev_lookup_mutex);
|
||||||
|
/*
|
||||||
|
* A list of struct nvgpu_nvs_domain_ioctl objects.
|
||||||
|
*/
|
||||||
|
static LIST_HEAD(cdev_lookup_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Priv data for an open domain device file.
|
||||||
|
*
|
||||||
|
* While a domain device is open, it holds a ref to the domain.
|
||||||
|
*/
|
||||||
|
struct nvgpu_nvs_domain_file_private {
|
||||||
|
struct gk20a *g;
|
||||||
|
struct nvgpu_nvs_domain *domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct nvgpu_nvs_domain_ioctl *nvgpu_nvs_lookup_cdev(dev_t dev)
|
||||||
|
{
|
||||||
|
struct nvgpu_nvs_domain_ioctl *ioctl, *ret = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&cdev_lookup_mutex);
|
||||||
|
|
||||||
|
list_for_each_entry(ioctl, &cdev_lookup_list, list) {
|
||||||
|
if (ioctl->cdev->dev == dev) {
|
||||||
|
/* put back in nvgpu_nvs_domain_dev_release */
|
||||||
|
nvgpu_nvs_domain_get(ioctl->g, ioctl->domain);
|
||||||
|
ret = ioctl;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&cdev_lookup_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int nvgpu_nvs_dev_open(struct inode *inode, struct file *filp)
|
int nvgpu_nvs_dev_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
struct nvgpu_cdev *cdev;
|
struct nvgpu_cdev *cdev;
|
||||||
@@ -48,6 +101,190 @@ int nvgpu_nvs_dev_release(struct inode *inode, struct file *filp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nvgpu_nvs_domain_dev_do_open(struct gk20a *g,
|
||||||
|
struct nvgpu_nvs_domain *domain,
|
||||||
|
struct file *filp)
|
||||||
|
{
|
||||||
|
struct nvgpu_nvs_domain_file_private *priv;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_nvs, "opening domain %s",
|
||||||
|
domain->parent->name);
|
||||||
|
|
||||||
|
g = nvgpu_get(g);
|
||||||
|
if (!g)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
priv = nvgpu_kzalloc(g, sizeof(*priv));
|
||||||
|
if (!priv) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto put_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->g = g;
|
||||||
|
priv->domain = domain;
|
||||||
|
filp->private_data = priv;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
put_ref:
|
||||||
|
nvgpu_put(g);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvgpu_nvs_domain_dev_open(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
struct nvgpu_nvs_domain_ioctl *ioctl;
|
||||||
|
struct cdev *cdev = inode->i_cdev;
|
||||||
|
struct nvgpu_nvs_domain *domain;
|
||||||
|
struct gk20a *g;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
ioctl = nvgpu_nvs_lookup_cdev(cdev->dev);
|
||||||
|
if (ioctl == NULL) {
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
g = ioctl->g;
|
||||||
|
domain = ioctl->domain;
|
||||||
|
|
||||||
|
err = nvgpu_nvs_domain_dev_do_open(g, domain, filp);
|
||||||
|
if (err) {
|
||||||
|
nvgpu_nvs_domain_put(g, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvgpu_nvs_domain_dev_release(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
struct nvgpu_nvs_domain_file_private *priv = filp->private_data;
|
||||||
|
struct nvgpu_nvs_domain *domain;
|
||||||
|
struct gk20a *g;
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
g = priv->g;
|
||||||
|
domain = priv->domain;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_nvs, "releasing domain %s",
|
||||||
|
domain->parent->name);
|
||||||
|
|
||||||
|
/* this was taken when the file was opened */
|
||||||
|
nvgpu_nvs_domain_put(g, domain);
|
||||||
|
|
||||||
|
nvgpu_kfree(g, priv);
|
||||||
|
nvgpu_put(g);
|
||||||
|
filp->private_data = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations nvgpu_nvs_domain_ops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = nvgpu_nvs_domain_dev_open,
|
||||||
|
.release = nvgpu_nvs_domain_dev_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nvgpu_nvs_domain *nvgpu_nvs_domain_get_from_file(int fd)
|
||||||
|
{
|
||||||
|
struct nvgpu_nvs_domain_file_private *priv;
|
||||||
|
struct nvgpu_nvs_domain *domain;
|
||||||
|
struct file *f = fget(fd);
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (f->f_op != &nvgpu_nvs_domain_ops) {
|
||||||
|
fput(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = (struct nvgpu_nvs_domain_file_private *)f->private_data;
|
||||||
|
domain = priv->domain;
|
||||||
|
|
||||||
|
nvgpu_log(priv->g, gpu_dbg_fn | gpu_dbg_nvs, "domain %s",
|
||||||
|
domain->parent->name);
|
||||||
|
nvgpu_nvs_domain_get(priv->g, domain);
|
||||||
|
fput(f);
|
||||||
|
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_domain_dev(struct gk20a *g,
|
||||||
|
struct nvgpu_nvs_domain *domain)
|
||||||
|
{
|
||||||
|
struct device *dev = dev_from_gk20a(g);
|
||||||
|
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
|
||||||
|
struct nvs_domain *nvs_domain = domain->parent;
|
||||||
|
struct nvgpu_nvs_domain_ioctl *ioctl = domain->ioctl;
|
||||||
|
char name[sizeof("nvsched-") + ARRAY_SIZE(nvs_domain->name)];
|
||||||
|
struct nvgpu_class *class;
|
||||||
|
dev_t devno;
|
||||||
|
unsigned int minor;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_nvs, " ");
|
||||||
|
|
||||||
|
class = nvgpu_get_v2_user_class(g);
|
||||||
|
if (class == NULL) {
|
||||||
|
/* MIG? */
|
||||||
|
dev_err(dev, "unsupported GPU for scheduling");
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
minor = nvgpu_allocate_cdev_minor(g);
|
||||||
|
devno = MKDEV(MAJOR(l->cdev_region), minor);
|
||||||
|
err = register_chrdev_region(devno, 1, dev_name(dev));
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "failed to allocate devno");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(name, "nvsched-%s", nvs_domain->name);
|
||||||
|
|
||||||
|
ioctl->g = g;
|
||||||
|
ioctl->domain = domain;
|
||||||
|
INIT_LIST_HEAD(&ioctl->list);
|
||||||
|
ioctl->cdev = cdev_alloc();
|
||||||
|
ioctl->cdev->ops = &nvgpu_nvs_domain_ops;
|
||||||
|
ioctl->class = class;
|
||||||
|
err = nvgpu_create_device(dev, devno, name,
|
||||||
|
ioctl->cdev, &ioctl->dev, class);
|
||||||
|
if (err) {
|
||||||
|
unregister_chrdev_region(devno, 1);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&ioctl->list, &cdev_lookup_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delete_domain_dev(struct gk20a *g,
|
||||||
|
struct nvgpu_nvs_domain *domain)
|
||||||
|
{
|
||||||
|
struct nvgpu_nvs_domain_ioctl *ioctl = domain->ioctl;
|
||||||
|
dev_t dev = ioctl->cdev->dev;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_nvs, " ");
|
||||||
|
/*
|
||||||
|
* note: we're under the lookup lock, so no new open would succeed after this.
|
||||||
|
*
|
||||||
|
* nvgpu_nvs_domain_dev_open() might be waiting for the lock now. Open
|
||||||
|
* cdevs remain accessible even after cdev deletion, but we won't get
|
||||||
|
* here until all successfully opened devices have been closed because
|
||||||
|
* they hold domain refs.
|
||||||
|
*/
|
||||||
|
list_del(&ioctl->list);
|
||||||
|
|
||||||
|
device_destroy(nvgpu_class_get_class(ioctl->class), dev);
|
||||||
|
cdev_del(ioctl->cdev);
|
||||||
|
unregister_chrdev_region(dev, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int nvgpu_nvs_ioctl_create_domain(
|
static int nvgpu_nvs_ioctl_create_domain(
|
||||||
struct gk20a *g,
|
struct gk20a *g,
|
||||||
struct nvgpu_nvs_ioctl_create_domain *dom_args)
|
struct nvgpu_nvs_ioctl_create_domain *dom_args)
|
||||||
@@ -55,6 +292,8 @@ static int nvgpu_nvs_ioctl_create_domain(
|
|||||||
struct nvgpu_nvs_domain *domain = NULL;
|
struct nvgpu_nvs_domain *domain = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_nvs, " ");
|
||||||
|
|
||||||
if (dom_args->reserved1 != 0) {
|
if (dom_args->reserved1 != 0) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -88,12 +327,36 @@ static int nvgpu_nvs_ioctl_create_domain(
|
|||||||
|
|
||||||
dom_args->domain_params.dom_id = domain->id;
|
dom_args->domain_params.dom_id = domain->id;
|
||||||
|
|
||||||
|
domain->ioctl = nvgpu_kzalloc(g, sizeof(*domain->ioctl));
|
||||||
|
if (domain->ioctl == NULL) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto del_domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&cdev_lookup_mutex);
|
||||||
|
err = create_domain_dev(g, domain);
|
||||||
|
mutex_unlock(&cdev_lookup_mutex);
|
||||||
|
if (err != 0) {
|
||||||
|
goto free_ioctl;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
free_ioctl:
|
||||||
|
nvgpu_kfree(g, domain->ioctl);
|
||||||
|
del_domain:
|
||||||
|
nvgpu_nvs_del_domain(g, domain->id);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nvgpu_nvs_ioctl_remove_domain(struct gk20a *g,
|
static int nvgpu_nvs_ioctl_remove_domain(struct gk20a *g,
|
||||||
struct nvgpu_nvs_ioctl_remove_domain *args)
|
struct nvgpu_nvs_ioctl_remove_domain *args)
|
||||||
{
|
{
|
||||||
|
struct nvgpu_nvs_domain_ioctl *ioctl;
|
||||||
|
struct nvgpu_nvs_domain *domain;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_nvs, " ");
|
||||||
|
|
||||||
if (args->reserved1 != 0) {
|
if (args->reserved1 != 0) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -102,10 +365,31 @@ static int nvgpu_nvs_ioctl_remove_domain(struct gk20a *g,
|
|||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nvgpu_nvs_del_domain(g, args->dom_id);
|
domain = nvgpu_nvs_domain_by_id(g, args->dom_id);
|
||||||
|
if (domain == NULL) {
|
||||||
|
nvgpu_err(g, "domain %llu does not exist!", args->dom_id);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl = domain->ioctl;
|
||||||
|
|
||||||
|
mutex_lock(&cdev_lookup_mutex);
|
||||||
|
|
||||||
|
nvgpu_nvs_domain_put(g, domain);
|
||||||
|
ret = nvgpu_nvs_del_domain(g, args->dom_id);
|
||||||
|
|
||||||
|
/* note: the internal default domain lacks ->ioctl */
|
||||||
|
if (ret == 0 && ioctl != NULL) {
|
||||||
|
delete_domain_dev(g, domain);
|
||||||
|
nvgpu_kfree(g, ioctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&cdev_lookup_mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nvgpu_nvs_ioctl_query_domains(
|
static int nvgpu_nvs_ioctl_query_domains_locked(
|
||||||
struct gk20a *g,
|
struct gk20a *g,
|
||||||
void __user *user_arg,
|
void __user *user_arg,
|
||||||
struct nvgpu_nvs_ioctl_query_domains *args)
|
struct nvgpu_nvs_ioctl_query_domains *args)
|
||||||
@@ -117,6 +401,8 @@ static int nvgpu_nvs_ioctl_query_domains(
|
|||||||
struct nvgpu_nvs_ioctl_domain *args_domains =
|
struct nvgpu_nvs_ioctl_domain *args_domains =
|
||||||
(void __user *)(uintptr_t)args->domains;
|
(void __user *)(uintptr_t)args->domains;
|
||||||
|
|
||||||
|
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_nvs, " ");
|
||||||
|
|
||||||
if (args->reserved0 != 0) {
|
if (args->reserved0 != 0) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -130,7 +416,7 @@ static int nvgpu_nvs_ioctl_query_domains(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* First call variant: return number of domains. */
|
/* First call variant: return number of domains. */
|
||||||
args->nr = nvgpu_nvs_domain_count(g);
|
args->nr = nvs_domain_count(g->scheduler->sched);
|
||||||
if (copy_to_user(user_arg, args, sizeof(*args))) {
|
if (copy_to_user(user_arg, args, sizeof(*args))) {
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
@@ -149,8 +435,8 @@ static int nvgpu_nvs_ioctl_query_domains(
|
|||||||
|
|
||||||
nvgpu_dom = nvs_dom->priv;
|
nvgpu_dom = nvs_dom->priv;
|
||||||
|
|
||||||
nvs_dbg(g, "Copying dom #%u [%s] (%llu)",
|
nvs_dbg(g, "Copying dom #%u [%s] (%llu) (%u refs)",
|
||||||
index, nvs_dom->name, nvgpu_dom->id);
|
index, nvs_dom->name, nvgpu_dom->id, nvgpu_dom->ref);
|
||||||
|
|
||||||
(void)memset(&dom, 0, sizeof(dom));
|
(void)memset(&dom, 0, sizeof(dom));
|
||||||
|
|
||||||
@@ -173,6 +459,19 @@ static int nvgpu_nvs_ioctl_query_domains(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nvgpu_nvs_ioctl_query_domains(
|
||||||
|
struct gk20a *g,
|
||||||
|
void __user *user_arg,
|
||||||
|
struct nvgpu_nvs_ioctl_query_domains *args)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
nvgpu_mutex_acquire(&g->sched_mutex);
|
||||||
|
err = nvgpu_nvs_ioctl_query_domains_locked(g, user_arg, args);
|
||||||
|
nvgpu_mutex_release(&g->sched_mutex);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
long nvgpu_nvs_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
long nvgpu_nvs_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
u8 buf[NVGPU_NVS_IOCTL_MAX_ARG_SIZE] = { 0 };
|
u8 buf[NVGPU_NVS_IOCTL_MAX_ARG_SIZE] = { 0 };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2021-2022, 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,
|
||||||
@@ -24,5 +24,6 @@ int nvgpu_nvs_dev_release(struct inode *inode, struct file *filp);
|
|||||||
long nvgpu_nvs_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
long nvgpu_nvs_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||||
ssize_t nvgpu_nvs_dev_read(struct file *filp, char __user *buf,
|
ssize_t nvgpu_nvs_dev_read(struct file *filp, char __user *buf,
|
||||||
size_t size, loff_t *off);
|
size_t size, loff_t *off);
|
||||||
|
struct nvgpu_nvs_domain *nvgpu_nvs_domain_get_from_file(int fd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2021-2022, 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,
|
||||||
@@ -87,6 +87,14 @@ struct nvgpu_nvs_ioctl_create_domain {
|
|||||||
__u64 reserved1;
|
__u64 reserved1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NVGPU_NVS_IOCTL_REMOVE_DOMAIN
|
||||||
|
*
|
||||||
|
* Remove a domain that has been previously created.
|
||||||
|
*
|
||||||
|
* The domain must be empty; it must have no TSGs bound to it. The domain's
|
||||||
|
* device node must not be open by anyone.
|
||||||
|
*/
|
||||||
struct nvgpu_nvs_ioctl_remove_domain {
|
struct nvgpu_nvs_ioctl_remove_domain {
|
||||||
/*
|
/*
|
||||||
* In: a domain_id to remove.
|
* In: a domain_id to remove.
|
||||||
|
|||||||
Reference in New Issue
Block a user