Skip to content

Commit

Permalink
drm/nouveau: implement new VM_BIND UAPI
Browse files Browse the repository at this point in the history
This commit provides the implementation for the new uapi motivated by the
Vulkan API. It allows user mode drivers (UMDs) to:

1) Initialize a GPU virtual address (VA) space via the new
   DRM_IOCTL_NOUVEAU_VM_INIT ioctl for UMDs to specify the portion of VA
   space managed by the kernel and userspace, respectively.

2) Allocate and free a VA space region as well as bind and unbind memory
   to the GPUs VA space via the new DRM_IOCTL_NOUVEAU_VM_BIND ioctl.
   UMDs can request the named operations to be processed either
   synchronously or asynchronously. It supports DRM syncobjs
   (incl. timelines) as synchronization mechanism. The management of the
   GPU VA mappings is implemented with the DRM GPU VA manager.

3) Execute push buffers with the new DRM_IOCTL_NOUVEAU_EXEC ioctl. The
   execution happens asynchronously. It supports DRM syncobj (incl.
   timelines) as synchronization mechanism. DRM GEM object locking is
   handled with drm_exec.

Both, DRM_IOCTL_NOUVEAU_VM_BIND and DRM_IOCTL_NOUVEAU_EXEC, use the DRM
GPU scheduler for the asynchronous paths.

Signed-off-by: Danilo Krummrich <dakr@redhat.com>
  • Loading branch information
dakr authored and intel-lab-lkp committed Jan 18, 2023
1 parent beef79d commit 85eb5d5
Show file tree
Hide file tree
Showing 11 changed files with 1,295 additions and 4 deletions.
3 changes: 3 additions & 0 deletions Documentation/gpu/driver-uapi.rst
Expand Up @@ -13,4 +13,7 @@ drm/nouveau uAPI
VM_BIND / EXEC uAPI
-------------------

.. kernel-doc:: drivers/gpu/drm/nouveau/nouveau_exec.c
:doc: Overview

.. kernel-doc:: include/uapi/drm/nouveau_drm.h
2 changes: 2 additions & 0 deletions drivers/gpu/drm/nouveau/Kbuild
Expand Up @@ -47,6 +47,8 @@ nouveau-y += nouveau_prime.o
nouveau-y += nouveau_sgdma.o
nouveau-y += nouveau_ttm.o
nouveau-y += nouveau_vmm.o
nouveau-y += nouveau_exec.o
nouveau-y += nouveau_sched.o
nouveau-y += nouveau_uvmm.o

# DRM - modesetting
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/nouveau/Kconfig
Expand Up @@ -10,6 +10,8 @@ config DRM_NOUVEAU
select DRM_KMS_HELPER
select DRM_TTM
select DRM_TTM_HELPER
select DRM_EXEC
select DRM_SCHED
select I2C
select I2C_ALGOBIT
select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT
Expand Down
16 changes: 16 additions & 0 deletions drivers/gpu/drm/nouveau/nouveau_abi16.c
Expand Up @@ -35,6 +35,7 @@
#include "nouveau_chan.h"
#include "nouveau_abi16.h"
#include "nouveau_vmm.h"
#include "nouveau_sched.h"

static struct nouveau_abi16 *
nouveau_abi16(struct drm_file *file_priv)
Expand Down Expand Up @@ -125,6 +126,17 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
{
struct nouveau_abi16_ntfy *ntfy, *temp;

/* When a client exits without waiting for it's queued up jobs to
* finish it might happen that we fault the channel. This is due to
* drm_file_free() calling drm_gem_release() before the postclose()
* callback. Hence, we can't tear down this scheduler entity before
* uvmm mappings are unmapped. Currently, we can't detect this case.
*
* However, this should be rare and harmless, since the channel isn't
* needed anymore.
*/
nouveau_sched_entity_fini(&chan->sched_entity);

/* wait for all activity to stop before cleaning up */
if (chan->chan)
nouveau_channel_idle(chan->chan);
Expand Down Expand Up @@ -311,6 +323,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
if (ret)
goto done;

ret = nouveau_sched_entity_init(&chan->sched_entity, &drm->sched);
if (ret)
goto done;

init->channel = chan->chan->chid;

if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_abi16.h
Expand Up @@ -26,6 +26,7 @@ struct nouveau_abi16_chan {
struct nouveau_bo *ntfy;
struct nouveau_vma *ntfy_vma;
struct nvkm_mm heap;
struct nouveau_sched_entity sched_entity;
};

struct nouveau_abi16 {
Expand Down
23 changes: 21 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_drm.c
Expand Up @@ -71,6 +71,7 @@
#include "nouveau_svm.h"
#include "nouveau_dmem.h"
#include "nouveau_uvmm.h"
#include "nouveau_sched.h"

DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
"DRM_UT_CORE",
Expand Down Expand Up @@ -192,6 +193,7 @@ nouveau_cli_fini(struct nouveau_cli *cli)
flush_work(&cli->work);
WARN_ON(!list_empty(&cli->worker));

nouveau_sched_entity_fini(&cli->sched_entity);
usif_client_fini(cli);
nouveau_uvmm_fini(&cli->uvmm);
nouveau_vmm_fini(&cli->svm);
Expand Down Expand Up @@ -299,6 +301,11 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
}

cli->mem = &mems[ret];

ret = nouveau_sched_entity_init(&cli->sched_entity, &drm->sched);
if (ret)
goto done;

return 0;
done:
if (ret)
Expand Down Expand Up @@ -611,8 +618,13 @@ nouveau_drm_device_init(struct drm_device *dev)
pm_runtime_put(dev->dev);
}

return 0;
ret = nouveau_sched_init(&drm->sched, drm);
if (ret)
goto fail_sched_init;

return 0;
fail_sched_init:
nouveau_display_fini(dev, false, false);
fail_dispinit:
nouveau_display_destroy(dev);
fail_dispctor:
Expand All @@ -637,6 +649,8 @@ nouveau_drm_device_fini(struct drm_device *dev)
struct nouveau_cli *cli, *temp_cli;
struct nouveau_drm *drm = nouveau_drm(dev);

nouveau_sched_fini(&drm->sched);

if (nouveau_pmops_runtime()) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
Expand Down Expand Up @@ -1177,6 +1191,9 @@ nouveau_ioctls[] = {
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(NOUVEAU_VM_INIT, nouveau_ioctl_vm_init, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(NOUVEAU_VM_BIND, nouveau_ioctl_vm_bind, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(NOUVEAU_EXEC, nouveau_ioctl_exec, DRM_RENDER_ALLOW),
};

long
Expand Down Expand Up @@ -1224,7 +1241,9 @@ nouveau_driver_fops = {
static struct drm_driver
driver_stub = {
.driver_features =
DRIVER_GEM | DRIVER_MODESET | DRIVER_RENDER
DRIVER_GEM | DRIVER_MODESET | DRIVER_RENDER |
DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE |
DRIVER_GEM_GPUVA
#if defined(CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT)
| DRIVER_KMS_LEGACY_CONTEXT
#endif
Expand Down
9 changes: 7 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Expand Up @@ -10,8 +10,8 @@
#define DRIVER_DATE "20120801"

#define DRIVER_MAJOR 1
#define DRIVER_MINOR 3
#define DRIVER_PATCHLEVEL 1
#define DRIVER_MINOR 4
#define DRIVER_PATCHLEVEL 0

/*
* 1.1.1:
Expand Down Expand Up @@ -63,6 +63,7 @@ struct platform_device;

#include "nouveau_fence.h"
#include "nouveau_bios.h"
#include "nouveau_sched.h"
#include "nouveau_vmm.h"
#include "nouveau_uvmm.h"

Expand Down Expand Up @@ -94,6 +95,8 @@ struct nouveau_cli {
struct nouveau_vmm svm;
struct nouveau_uvmm uvmm;

struct nouveau_sched_entity sched_entity;

const struct nvif_mclass *mem;

struct list_head head;
Expand Down Expand Up @@ -305,6 +308,8 @@ struct nouveau_drm {
struct mutex lock;
bool component_registered;
} audio;

struct drm_gpu_scheduler sched;
};

static inline struct nouveau_drm *
Expand Down

0 comments on commit 85eb5d5

Please sign in to comment.