summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAri Hirvonen <ahirvonen@nvidia.com>2015-06-15 15:26:37 +0900
committerAlexandre Courbot <acourbot@nvidia.com>2016-01-15 14:32:54 +0900
commitce8a0340c70fa3f181e0b0725322b29f36166fa3 (patch)
treeaef66a1ccd08d131b87fc10c6d4471a144faeac2
parenteb87d86fd2c1395485d5cea93fe6159146fd1d9b (diff)
downloadnouveau-ce8a0340c70fa3f181e0b0725322b29f36166fa3.tar.gz
drm/nouveau: add GEM_SET_TILING staging ioctl
Add new NOUVEAU_GEM_SET_TILING ioctl to set correct tiling mode for imported dma-bufs. This ioctl is staging for now and enabled with the "staging_tiling" module option. Signed-off-by: Ari Hirvonen <ahirvonen@nvidia.com> [acourbot@nvidia.com: carry upstream, many fixes] Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
-rw-r--r--drm/nouveau/nouveau_bo.c27
-rw-r--r--drm/nouveau/nouveau_bo.h2
-rw-r--r--drm/nouveau/nouveau_drm.c1
-rw-r--r--drm/nouveau/nouveau_gem.c54
-rw-r--r--drm/nouveau/nouveau_gem.h2
-rw-r--r--drm/nouveau/nouveau_ttm.c22
-rw-r--r--drm/nouveau/uapi/drm/nouveau_drm.h8
7 files changed, 95 insertions, 21 deletions
diff --git a/drm/nouveau/nouveau_bo.c b/drm/nouveau/nouveau_bo.c
index 78f520d05..711e40195 100644
--- a/drm/nouveau/nouveau_bo.c
+++ b/drm/nouveau/nouveau_bo.c
@@ -173,6 +173,33 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
*size = roundup(*size, PAGE_SIZE);
}
+void
+nouveau_bo_update_tiling(struct nouveau_drm *drm, struct nouveau_bo *nvbo,
+ struct nvkm_mem *mem)
+{
+ switch (drm->device.info.family) {
+ case NV_DEVICE_INFO_V0_TNT:
+ case NV_DEVICE_INFO_V0_CELSIUS:
+ case NV_DEVICE_INFO_V0_KELVIN:
+ case NV_DEVICE_INFO_V0_RANKINE:
+ case NV_DEVICE_INFO_V0_CURIE:
+ break;
+ case NV_DEVICE_INFO_V0_TESLA:
+ if (drm->device.info.chipset != 0x50)
+ mem->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
+ break;
+ case NV_DEVICE_INFO_V0_FERMI:
+ case NV_DEVICE_INFO_V0_KEPLER:
+ case NV_DEVICE_INFO_V0_MAXWELL:
+ mem->memtype = (nvbo->tile_flags & 0xff00) >> 8;
+ break;
+ default:
+ NV_WARN(drm, "%s: unhandled family type %x\n", __func__,
+ drm->device.info.family);
+ break;
+ }
+}
+
int
nouveau_bo_new(struct drm_device *dev, int size, int align,
uint32_t flags, uint32_t tile_mode, uint32_t tile_flags,
diff --git a/drm/nouveau/nouveau_bo.h b/drm/nouveau/nouveau_bo.h
index e42360983..87d07e353 100644
--- a/drm/nouveau/nouveau_bo.h
+++ b/drm/nouveau/nouveau_bo.h
@@ -69,6 +69,8 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo)
extern struct ttm_bo_driver nouveau_bo_driver;
void nouveau_bo_move_init(struct nouveau_drm *);
+void nouveau_bo_update_tiling(struct nouveau_drm *, struct nouveau_bo *,
+ struct nvkm_mem *);
int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags,
u32 tile_mode, u32 tile_flags, struct sg_table *sg,
struct reservation_object *robj,
diff --git a/drm/nouveau/nouveau_drm.c b/drm/nouveau/nouveau_drm.c
index 2f2f252e3..f1866a272 100644
--- a/drm/nouveau/nouveau_drm.c
+++ b/drm/nouveau/nouveau_drm.c
@@ -876,6 +876,7 @@ nouveau_ioctls[] = {
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_SET_TILING, nouveau_gem_ioctl_set_tiling, DRM_AUTH|DRM_RENDER_ALLOW),
};
long
diff --git a/drm/nouveau/nouveau_gem.c b/drm/nouveau/nouveau_gem.c
index a0865c49e..789f7aaef 100644
--- a/drm/nouveau/nouveau_gem.c
+++ b/drm/nouveau/nouveau_gem.c
@@ -175,6 +175,60 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
}
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 (!nvkm_fb_memtype_valid(pfb, req->tile_flags)) {
+ NV_PRINTK(err, cli, "bad page flags: 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);
+
+ /* We can only change tiling on PRIME-imported buffers */
+ if (nvbo->bo.type != ttm_bo_type_sg) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ 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;
+
+ nvbo->tile_mode = req->tile_mode;
+ nvbo->tile_flags = req->tile_flags;
+
+ nouveau_bo_update_tiling(drm, nvbo, nvbo->bo.mem.mm_node);
+
+ /* remap over existing mapping with new tile parameters */
+ vma = nouveau_bo_vma_find(nvbo, cli->vm);
+ if (vma)
+ 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,
struct nouveau_bo **pnvbo)
diff --git a/drm/nouveau/nouveau_gem.h b/drm/nouveau/nouveau_gem.h
index e4049faca..56e741d98 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 *,
diff --git a/drm/nouveau/nouveau_ttm.c b/drm/nouveau/nouveau_ttm.c
index d2e7d209f..31277e57a 100644
--- a/drm/nouveau/nouveau_ttm.c
+++ b/drm/nouveau/nouveau_ttm.c
@@ -150,27 +150,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
node->page_shift = 12;
- switch (drm->device.info.family) {
- case NV_DEVICE_INFO_V0_TNT:
- case NV_DEVICE_INFO_V0_CELSIUS:
- case NV_DEVICE_INFO_V0_KELVIN:
- case NV_DEVICE_INFO_V0_RANKINE:
- case NV_DEVICE_INFO_V0_CURIE:
- break;
- case NV_DEVICE_INFO_V0_TESLA:
- if (drm->device.info.chipset != 0x50)
- node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
- break;
- case NV_DEVICE_INFO_V0_FERMI:
- case NV_DEVICE_INFO_V0_KEPLER:
- case NV_DEVICE_INFO_V0_MAXWELL:
- node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
- break;
- default:
- NV_WARN(drm, "%s: unhandled family type %x\n", __func__,
- drm->device.info.family);
- break;
- }
+ nouveau_bo_update_tiling(drm, nvbo, node);
mem->mm_node = node;
mem->start = 0;
diff --git a/drm/nouveau/uapi/drm/nouveau_drm.h b/drm/nouveau/uapi/drm/nouveau_drm.h
index 500d82aec..a73196cea 100644
--- a/drm/nouveau/uapi/drm/nouveau_drm.h
+++ b/drm/nouveau/uapi/drm/nouveau_drm.h
@@ -58,6 +58,12 @@ struct drm_nouveau_gem_new {
__u32 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 {
__u32 valid;
@@ -134,11 +140,13 @@ struct drm_nouveau_gem_cpu_fini {
#define DRM_NOUVEAU_GEM_CPU_PREP 0x42
#define DRM_NOUVEAU_GEM_CPU_FINI 0x43
#define DRM_NOUVEAU_GEM_INFO 0x44
+#define DRM_NOUVEAU_GEM_SET_TILING 0x50
#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_PUSHBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf)
#define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep)
#define DRM_IOCTL_NOUVEAU_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_FINI, struct drm_nouveau_gem_cpu_fini)
#define DRM_IOCTL_NOUVEAU_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_INFO, struct drm_nouveau_gem_info)
+#define DRM_IOCTL_NOUVEAU_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_SET_TILING, struct drm_nouveau_gem_set_tiling)
#endif /* __NOUVEAU_DRM_H__ */