From 22ec8ae4d72daabc574b0400848dbff1a9abe698 Mon Sep 17 00:00:00 2001 From: Jérôme Glisse Date: Thu, 3 Aug 2017 18:20:55 -0400 Subject: drm/nouveau/compote: memory allocation ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add memory allocation ioctl. Very basic and simple linear allocation inside GART. Signed-off-by: Jérôme Glisse --- drivers/gpu/drm/nouveau/compote/Kbuild | 1 + drivers/gpu/drm/nouveau/compote/compote-driver.c | 28 ++++- drivers/gpu/drm/nouveau/compote/compote-memory.c | 152 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/compote/compote.h | 15 +++ drivers/gpu/drm/nouveau/nouveau_bo.h | 3 + 5 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/nouveau/compote/compote-memory.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/compote/Kbuild b/drivers/gpu/drm/nouveau/compote/Kbuild index 89af6841ab15..9c6f3a2ae9de 100644 --- a/drivers/gpu/drm/nouveau/compote/Kbuild +++ b/drivers/gpu/drm/nouveau/compote/Kbuild @@ -1,3 +1,4 @@ ifdef CONFIG_DRM_COMPOTE compote-y := compote/compote-driver.o +compote-y += compote/compote-memory.o endif diff --git a/drivers/gpu/drm/nouveau/compote/compote-driver.c b/drivers/gpu/drm/nouveau/compote/compote-driver.c index 409e4c803c26..6e05ffc351b3 100644 --- a/drivers/gpu/drm/nouveau/compote/compote-driver.c +++ b/drivers/gpu/drm/nouveau/compote/compote-driver.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "compote.h" #include @@ -169,7 +170,32 @@ static long compote_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return -EINVAL; + struct compote_file *cfile = file->private_data; + void __user *uarg = (void __user *)arg; + long ret; + + if (!cfile) + return -EINVAL; + + ret = pm_runtime_get_sync(cfile->cdevice->nvdrm->dev->dev); + if (WARN_ON(ret < 0 && ret != -EACCES)) + return ret; + + switch (cmd) { + case COMPOTE_IOCTL_MEM_ALLOC: + ret = compote_ioctl_mem_alloc(cfile, uarg); + break; + case COMPOTE_IOCTL_MEM_FREE: + ret = compote_ioctl_mem_free(cfile, uarg); + break; + default: + ret = -EINVAL; + break; + } + + pm_runtime_mark_last_busy(cfile->cdevice->nvdrm->dev->dev); + pm_runtime_put_autosuspend(cfile->cdevice->nvdrm->dev->dev); + return ret; } static const struct file_operations compote_fops = { diff --git a/drivers/gpu/drm/nouveau/compote/compote-memory.c b/drivers/gpu/drm/nouveau/compote/compote-memory.c new file mode 100644 index 000000000000..55fca9092846 --- /dev/null +++ b/drivers/gpu/drm/nouveau/compote/compote-memory.c @@ -0,0 +1,152 @@ +/* + * Copyright 2017 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Authors: Jérôme Glisse + */ +#include +#include +#include +#include +#include +#include +#include "compote.h" + +#include +#include + +#include "nouveau_ttm.h" +#include "nouveau_usif.h" +#include "nouveau_abi16.h" +#include "nouveau_bo.h" + +static struct compote_mo *compote_file_mo_find(struct compote_file *cfile, + uint64_t foffset) +{ + struct ttm_bo_device *bdev = &cfile->cdevice->nvdrm->ttm.bdev; + struct drm_vma_offset_node *node; + struct compote_mo *mo = NULL; + + drm_vma_offset_lock_lookup(&bdev->vma_manager); + node = drm_vma_offset_lookup_locked(&bdev->vma_manager, foffset, 1); + if (likely(node)) { + struct ttm_buffer_object *bo; + struct nouveau_bo *nvbo; + + bo = container_of(node, struct ttm_buffer_object, vma_node); + nvbo = nouveau_bo(bo); + mo = nvbo->mo; + if (!mo || mo->cfile != cfile || !kref_get_unless_zero(&mo->kref)) + mo = NULL; + } + drm_vma_offset_unlock_lookup(&bdev->vma_manager); + + return mo; +} + +static int compote_mo_new(struct compote_mo **mop, + struct compote_file *cfile, + uint64_t nbytes) +{ + uint32_t flags, tile_mode, tile_flags; + struct compote_mo *mo; + int align; + int ret; + + mo = kzalloc(sizeof(*mo), GFP_KERNEL); + if (mo == NULL) + return -ENOMEM; + + + align = 0; + tile_mode = 0; + tile_flags = 0; + flags = TTM_PL_FLAG_TT; + ret = nouveau_bo_new(&cfile->nvclient, nbytes, align, flags, tile_mode, + tile_flags, NULL, NULL, &mo->nvbo); + if (ret) + goto error_bo; + + mo->cfile = cfile; + mo->nvbo->mo = mo; + kref_init(&mo->kref); + mo->npages = PAGE_ALIGN(nbytes); + mo->foffset = drm_vma_node_offset_addr(&mo->nvbo->bo.vma_node); + + *mop = mo; + return 0; + +error_bo: + kfree(mo); + *mop = NULL; + return ret; +} + +static void compote_mo_kref_put(struct kref *kref) +{ + struct compote_mo *mo = container_of(kref, struct compote_mo, kref); + struct ttm_buffer_object *bo = &mo->nvbo->bo; + + ttm_bo_unref(&bo); + kfree(mo); +} + +void compote_mo_ref(struct compote_mo *mo) +{ + kref_get(&mo->kref); +} + +void compote_mo_unref(struct compote_mo *mo) +{ + kref_put(&mo->kref, compote_mo_kref_put); +} + +long compote_ioctl_mem_alloc(struct compote_file *cfile, void __user *uarg) +{ + struct compote_ioctl_mem_alloc arg; + struct compote_mo *mo = NULL; + int ret; + + ret = copy_from_user(&arg, uarg, sizeof(arg)); + if (ret) + return ret; + + ret = compote_mo_new(&mo, cfile, arg.nbytes); + + arg.foffset = ret ? -1UL : mo->foffset; + ret = copy_to_user(uarg, &arg, sizeof(arg)); + if (ret) { + compote_mo_unref(mo); + return ret; + } + + return 0; +} + +long compote_ioctl_mem_free(struct compote_file *cfile, void __user *uarg) +{ + struct compote_ioctl_mem_free arg; + struct compote_mo *mo = NULL; + int ret; + + ret = copy_from_user(&arg, uarg, sizeof(arg)); + if (ret) + return ret; + + mo = compote_file_mo_find(cfile, arg.foffset); + if (mo == NULL) + return -EINVAL; + + compote_mo_unref(mo); + compote_mo_unref(mo); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/compote/compote.h b/drivers/gpu/drm/nouveau/compote/compote.h index 40f437703259..c0d59960ceef 100644 --- a/drivers/gpu/drm/nouveau/compote/compote.h +++ b/drivers/gpu/drm/nouveau/compote/compote.h @@ -16,6 +16,7 @@ #ifndef COMPOTE_H #define COMPOTE_H +#include #include "nouveau_drv.h" #define COMPOTE_DEVICE_NAME "compote" @@ -34,4 +35,18 @@ struct compote_file { struct nouveau_cli nvclient; }; +struct compote_mo { + struct kref kref; + struct compote_file *cfile; + struct nouveau_bo *nvbo; + uint64_t npages; + uint64_t foffset; +}; + +long compote_ioctl_mem_alloc(struct compote_file *cfile, void __user *uarg); +long compote_ioctl_mem_free(struct compote_file *cfile, void __user *uarg); + +void compote_mo_ref(struct compote_mo *mo); +void compote_mo_unref(struct compote_mo *mo); + #endif /* COMPOTE_H */ diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index b46f3060b823..1031db2958e7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -41,6 +41,9 @@ struct nouveau_bo { int pin_refcnt; struct ttm_bo_kmap_obj dma_buf_vmap; + + /* for compote */ + void *mo; }; static inline struct nouveau_bo * -- cgit v1.2.3