From 404f779f732973b3d58a4a948230f11b64c8ac70 Mon Sep 17 00:00:00 2001 From: Ari Hirvonen Date: Mon, 16 Feb 2015 17:02:48 +0900 Subject: drm/nouveau: Set tile mode Add new NOUVEAU_GEM_SET_TILING ioctl to set correct tiling mode for imported dma-bufs. Signed-off-by: Ari Hirvonen Signed-off-by: Lauri Peltonen Signed-off-by: Alexandre Courbot --- drm/nouveau/include/uapi/drm/nouveau_drm.h | 8 +++++ drm/nouveau/nouveau_drm.c | 1 + drm/nouveau/nouveau_gem.c | 56 ++++++++++++++++++++++++++++++ drm/nouveau/nouveau_gem.h | 2 ++ 4 files changed, 67 insertions(+) diff --git a/drm/nouveau/include/uapi/drm/nouveau_drm.h b/drm/nouveau/include/uapi/drm/nouveau_drm.h index 01a4cf44d..34033d1cf 100644 --- a/drm/nouveau/include/uapi/drm/nouveau_drm.h +++ b/drm/nouveau/include/uapi/drm/nouveau_drm.h @@ -64,6 +64,12 @@ struct drm_nouveau_gem_new { uint32_t align; }; +struct drm_nouveau_gem_set_tiling { + uint32_t handle; + uint32_t tile_mode; + uint32_t tile_flags; +}; + #define NOUVEAU_GEM_MAX_BUFFERS 1024 struct drm_nouveau_gem_pushbuf_bo_presumed { uint32_t valid; @@ -156,8 +162,10 @@ struct drm_nouveau_gem_cpu_fini { #define DRM_NOUVEAU_GEM_CPU_FINI 0x43 #define DRM_NOUVEAU_GEM_INFO 0x44 #define DRM_NOUVEAU_GEM_PUSHBUF_2 0x45 +#define DRM_NOUVEAU_GEM_SET_TILING 0x46 #define DRM_IOCTL_NOUVEAU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new) +#define DRM_IOCTL_NOUVEAU_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_SET_TILING, struct drm_nouveau_gem_set_tiling) #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf) #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF_2 DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF_2, struct drm_nouveau_gem_pushbuf_2) #define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep) diff --git a/drm/nouveau/nouveau_drm.c b/drm/nouveau/nouveau_drm.c index 2908b6a14..dbb51410d 100644 --- a/drm/nouveau/nouveau_drm.c +++ b/drm/nouveau/nouveau_drm.c @@ -890,6 +890,7 @@ nouveau_ioctls[] = { DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_SET_TILING, nouveau_gem_ioctl_set_tiling, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF_2, nouveau_gem_ioctl_pushbuf_2, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW), diff --git a/drm/nouveau/nouveau_gem.c b/drm/nouveau/nouveau_gem.c index 0a553019c..e1c988cc2 100644 --- a/drm/nouveau/nouveau_gem.c +++ b/drm/nouveau/nouveau_gem.c @@ -172,6 +172,62 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) ttm_bo_unreserve(&nvbo->bo); } +int +nouveau_gem_ioctl_set_tiling(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_cli *cli = nouveau_cli(file_priv); + struct nvkm_fb *pfb = nvxx_fb(&drm->device); + struct drm_nouveau_gem_set_tiling *req = data; + struct drm_gem_object *gem; + struct nouveau_bo *nvbo; + struct nvkm_vma *vma; + int ret = 0; + + if (!pfb->memtype_valid(pfb, req->tile_flags)) { + NV_PRINTK(error, cli, "bad memtype: 0x%08x\n", req->tile_flags); + return -EINVAL; + } + + gem = drm_gem_object_lookup(dev, file_priv, req->handle); + + if (!gem) + return -ENOENT; + + nvbo = nouveau_gem_object(gem); + + if (nvbo->tile_mode != req->tile_mode || + nvbo->tile_flags != req->tile_flags) { + + ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL); + + if (ret) + goto out; + + vma = nouveau_bo_vma_find(nvbo, cli->vm); + + if (!vma) { + ret = -ENOENT; + } else { + struct nvkm_mem *mem = nvbo->bo.mem.mm_node; + + nvbo->tile_mode = req->tile_mode; + nvbo->tile_flags = req->tile_flags; + + /* Need to rewrite page tables */ + mem->memtype = (nvbo->tile_flags >> 8) & 0xff; + nvkm_vm_map(vma, nvbo->bo.mem.mm_node); + } + + ttm_bo_unreserve(&nvbo->bo); + } + +out: + drm_gem_object_unreference_unlocked(gem); + return ret; +} + int nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, uint32_t tile_mode, uint32_t tile_flags, diff --git a/drm/nouveau/nouveau_gem.h b/drm/nouveau/nouveau_gem.h index 07f54a4fe..9e4323f34 100644 --- a/drm/nouveau/nouveau_gem.h +++ b/drm/nouveau/nouveau_gem.h @@ -23,6 +23,8 @@ extern void nouveau_gem_object_del(struct drm_gem_object *); extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *); extern void nouveau_gem_object_close(struct drm_gem_object *, struct drm_file *); +extern int nouveau_gem_ioctl_set_tiling(struct drm_device *, void *, + struct drm_file *); extern int nouveau_gem_ioctl_new(struct drm_device *, void *, struct drm_file *); extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *, -- cgit v1.2.1