From 7a6007c309c9b0e573dc17ac9d81e8b5f173847d Mon Sep 17 00:00:00 2001 From: Mikko Rapeli Date: Thu, 15 Oct 2015 07:55:50 +0200 Subject: include/uapi/drm/sis_drm.h: move sis_file_private to drivers/gpu/drm/sis/sis_drv.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes userspace compile error: drm/sis_drm.h:68:19: error: field ‘obj_list’ has incomplete type struct list_head obj_list; Suggested by Emil Velikov at https://lkml.org/lkml/2015/6/3/792 Signed-off-by: Mikko Rapeli Signed-off-by: Dave Airlie --- include/uapi/drm/sis_drm.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include/uapi/drm') diff --git a/include/uapi/drm/sis_drm.h b/include/uapi/drm/sis_drm.h index df3763222d73..374858cdcdaa 100644 --- a/include/uapi/drm/sis_drm.h +++ b/include/uapi/drm/sis_drm.h @@ -64,8 +64,4 @@ typedef struct { unsigned long offset, size; } drm_sis_fb_t; -struct sis_file_private { - struct list_head obj_list; -}; - #endif /* __SIS_DRM_H__ */ -- cgit v1.2.3 From c76af02d90ee9e9d2ef478fc6f874ad2abcf3ec9 Mon Sep 17 00:00:00 2001 From: Mikko Rapeli Date: Thu, 15 Oct 2015 07:55:48 +0200 Subject: via_drm.h: move struct via_file_private definition to drivers/gpu/drm/via/via_drv.h Fixes userspace compile error since list_head is not exported to userspace headers. Suggested by Emil Velikov at https://lkml.org/lkml/2015/6/3/792 Signed-off-by: Mikko Rapeli Signed-off-by: Dave Airlie --- drivers/gpu/drm/via/via_drv.h | 4 ++++ include/uapi/drm/via_drm.h | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include/uapi/drm') diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 644093f5046c..286a785fab4f 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -102,6 +102,10 @@ typedef struct drm_via_private { uint32_t dma_diff; } drm_via_private_t; +struct via_file_private { + struct list_head obj_list; +}; + enum via_family { VIA_OTHER = 0, /* Baseline */ VIA_PRO_GROUP_A, /* Another video engine and DMA commands */ diff --git a/include/uapi/drm/via_drm.h b/include/uapi/drm/via_drm.h index 8b0533ccbd5a..45bc80c3714b 100644 --- a/include/uapi/drm/via_drm.h +++ b/include/uapi/drm/via_drm.h @@ -274,8 +274,4 @@ typedef struct drm_via_dmablit { drm_via_blitsync_t sync; } drm_via_dmablit_t; -struct via_file_private { - struct list_head obj_list; -}; - #endif /* _VIA_DRM_H_ */ -- cgit v1.2.3 From 62fb7a5e10962ac6ae2a2d2dbd3aedcb2a3e3257 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 28 Oct 2014 12:48:00 +0100 Subject: virtio-gpu: add 3d/virgl support Add the bits needed for opengl rendering support: query capabilities, new virtio commands, drm ioctls. Signed-off-by: Dave Airlie Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/Makefile | 3 +- drivers/gpu/drm/virtio/virtgpu_drv.c | 15 + drivers/gpu/drm/virtio/virtgpu_drv.h | 60 ++++ drivers/gpu/drm/virtio/virtgpu_gem.c | 41 +++ drivers/gpu/drm/virtio/virtgpu_ioctl.c | 573 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/virtio/virtgpu_kms.c | 133 +++++++- drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/virtio/virtgpu_vq.c | 265 +++++++++++++++ include/uapi/drm/Kbuild | 1 + include/uapi/drm/virtgpu_drm.h | 167 ++++++++++ include/uapi/linux/virtio_gpu.h | 112 ++++++- 11 files changed, 1368 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/virtio/virtgpu_ioctl.c create mode 100644 include/uapi/drm/virtgpu_drm.h (limited to 'include/uapi/drm') diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/Makefile index 2ee1602d77d4..da7bf192e462 100644 --- a/drivers/gpu/drm/virtio/Makefile +++ b/drivers/gpu/drm/virtio/Makefile @@ -6,6 +6,7 @@ ccflags-y := -Iinclude/drm virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_drm_bus.o virtgpu_gem.o \ virtgpu_fb.o virtgpu_display.o virtgpu_vq.o virtgpu_ttm.o \ - virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o + virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \ + virtgpu_ioctl.o obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 7d9610aaeff9..c27d3a30df0a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -73,6 +73,14 @@ static struct virtio_device_id id_table[] = { }; static unsigned int features[] = { +#ifdef __LITTLE_ENDIAN + /* + * Gallium command stream send by virgl is native endian. + * Because of that we only support little endian guests on + * little endian hosts. + */ + VIRTIO_GPU_F_VIRGL, +#endif }; static struct virtio_driver virtio_gpu_driver = { .feature_table = features, @@ -114,6 +122,8 @@ static struct drm_driver driver = { .set_busid = drm_virtio_set_busid, .load = virtio_gpu_driver_load, .unload = virtio_gpu_driver_unload, + .open = virtio_gpu_driver_open, + .postclose = virtio_gpu_driver_postclose, .dumb_create = virtio_gpu_mode_dumb_create, .dumb_map_offset = virtio_gpu_mode_dumb_mmap, @@ -125,8 +135,13 @@ static struct drm_driver driver = { #endif .gem_free_object = virtio_gpu_gem_free_object, + .gem_open_object = virtio_gpu_gem_object_open, + .gem_close_object = virtio_gpu_gem_object_close, .fops = &virtio_gpu_driver_fops, + .ioctls = virtio_gpu_ioctls, + .num_ioctls = DRM_VIRTIO_NUM_IOCTLS, + .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 6d4db2dba90b..27191088a701 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -146,6 +146,21 @@ struct virtio_gpu_queue { struct work_struct dequeue_work; }; +struct virtio_gpu_drv_capset { + uint32_t id; + uint32_t max_version; + uint32_t max_size; +}; + +struct virtio_gpu_drv_cap_cache { + struct list_head head; + void *caps_cache; + uint32_t id; + uint32_t version; + uint32_t size; + atomic_t is_valid; +}; + struct virtio_gpu_device { struct device *dev; struct drm_device *ddev; @@ -179,7 +194,13 @@ struct virtio_gpu_device { struct idr ctx_id_idr; spinlock_t ctx_id_idr_lock; + bool has_virgl_3d; + struct work_struct config_changed_work; + + struct virtio_gpu_drv_capset *capsets; + uint32_t num_capsets; + struct list_head cap_cache; }; struct virtio_gpu_fpriv { @@ -193,6 +214,8 @@ extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS]; /* virtio_kms.c */ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags); int virtio_gpu_driver_unload(struct drm_device *dev); +int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file); +void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file); /* virtio_gem.c */ void virtio_gpu_gem_free_object(struct drm_gem_object *gem_obj); @@ -203,6 +226,10 @@ int virtio_gpu_gem_create(struct drm_file *file, uint64_t size, struct drm_gem_object **obj_p, uint32_t *handle_p); +int virtio_gpu_gem_object_open(struct drm_gem_object *obj, + struct drm_file *file); +void virtio_gpu_gem_object_close(struct drm_gem_object *obj, + struct drm_file *file); struct virtio_gpu_object *virtio_gpu_alloc_object(struct drm_device *dev, size_t size, bool kernel, bool pinned); @@ -260,10 +287,43 @@ void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev, int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev); void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgdev, uint32_t resource_id); +int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx); +int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, + int idx, int version, + struct virtio_gpu_drv_cap_cache **cache_p); +void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, + uint32_t nlen, const char *name); +void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev, + uint32_t id); +void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev, + uint32_t ctx_id, + uint32_t resource_id); +void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev, + uint32_t ctx_id, + uint32_t resource_id); +void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev, + void *data, uint32_t data_size, + uint32_t ctx_id, struct virtio_gpu_fence **fence); +void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev, + uint32_t resource_id, uint32_t ctx_id, + uint64_t offset, uint32_t level, + struct virtio_gpu_box *box, + struct virtio_gpu_fence **fence); +void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, + uint32_t resource_id, uint32_t ctx_id, + uint64_t offset, uint32_t level, + struct virtio_gpu_box *box, + struct virtio_gpu_fence **fence); +void +virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev, + struct virtio_gpu_resource_create_3d *rc_3d, + struct virtio_gpu_fence **fence); void virtio_gpu_ctrl_ack(struct virtqueue *vq); void virtio_gpu_cursor_ack(struct virtqueue *vq); +void virtio_gpu_fence_ack(struct virtqueue *vq); void virtio_gpu_dequeue_ctrl_func(struct work_struct *work); void virtio_gpu_dequeue_cursor_func(struct work_struct *work); +void virtio_gpu_dequeue_fence_func(struct work_struct *work); /* virtio_gpu_display.c */ int virtio_gpu_framebuffer_init(struct drm_device *dev, diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index cfa0d27150bd..1feb7cee3f0d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -138,3 +138,44 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, drm_gem_object_unreference_unlocked(gobj); return 0; } + +int virtio_gpu_gem_object_open(struct drm_gem_object *obj, + struct drm_file *file) +{ + struct virtio_gpu_device *vgdev = obj->dev->dev_private; + struct virtio_gpu_fpriv *vfpriv = file->driver_priv; + struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); + int r; + + if (!vgdev->has_virgl_3d) + return 0; + + r = virtio_gpu_object_reserve(qobj, false); + if (r) + return r; + + virtio_gpu_cmd_context_attach_resource(vgdev, vfpriv->ctx_id, + qobj->hw_res_handle); + virtio_gpu_object_unreserve(qobj); + return 0; +} + +void virtio_gpu_gem_object_close(struct drm_gem_object *obj, + struct drm_file *file) +{ + struct virtio_gpu_device *vgdev = obj->dev->dev_private; + struct virtio_gpu_fpriv *vfpriv = file->driver_priv; + struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj); + int r; + + if (!vgdev->has_virgl_3d) + return; + + r = virtio_gpu_object_reserve(qobj, false); + if (r) + return; + + virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id, + qobj->hw_res_handle); + virtio_gpu_object_unreserve(qobj); +} diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c new file mode 100644 index 000000000000..4ef672b314c6 --- /dev/null +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -0,0 +1,573 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * All Rights Reserved. + * + * Authors: + * Dave Airlie + * Alon Levy + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "virtgpu_drv.h" +#include +#include "ttm/ttm_execbuf_util.h" + +static void convert_to_hw_box(struct virtio_gpu_box *dst, + const struct drm_virtgpu_3d_box *src) +{ + dst->x = cpu_to_le32(src->x); + dst->y = cpu_to_le32(src->y); + dst->z = cpu_to_le32(src->z); + dst->w = cpu_to_le32(src->w); + dst->h = cpu_to_le32(src->h); + dst->d = cpu_to_le32(src->d); +} + +static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct drm_virtgpu_map *virtio_gpu_map = data; + + return virtio_gpu_mode_dumb_mmap(file_priv, vgdev->ddev, + virtio_gpu_map->handle, + &virtio_gpu_map->offset); +} + +static int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket, + struct list_head *head) +{ + struct ttm_validate_buffer *buf; + struct ttm_buffer_object *bo; + struct virtio_gpu_object *qobj; + int ret; + + ret = ttm_eu_reserve_buffers(ticket, head, true, NULL); + if (ret != 0) + return ret; + + list_for_each_entry(buf, head, head) { + bo = buf->bo; + qobj = container_of(bo, struct virtio_gpu_object, tbo); + ret = ttm_bo_validate(bo, &qobj->placement, false, false); + if (ret) { + ttm_eu_backoff_reservation(ticket, head); + return ret; + } + } + return 0; +} + +static void virtio_gpu_unref_list(struct list_head *head) +{ + struct ttm_validate_buffer *buf; + struct ttm_buffer_object *bo; + struct virtio_gpu_object *qobj; + list_for_each_entry(buf, head, head) { + bo = buf->bo; + qobj = container_of(bo, struct virtio_gpu_object, tbo); + + drm_gem_object_unreference_unlocked(&qobj->gem_base); + } +} + +static int virtio_gpu_execbuffer(struct drm_device *dev, + struct drm_virtgpu_execbuffer *exbuf, + struct drm_file *drm_file) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv; + struct drm_gem_object *gobj; + struct virtio_gpu_fence *fence; + struct virtio_gpu_object *qobj; + int ret; + uint32_t *bo_handles = NULL; + void __user *user_bo_handles = NULL; + struct list_head validate_list; + struct ttm_validate_buffer *buflist = NULL; + int i; + struct ww_acquire_ctx ticket; + void *buf; + + if (vgdev->has_virgl_3d == false) + return -ENOSYS; + + INIT_LIST_HEAD(&validate_list); + if (exbuf->num_bo_handles) { + + bo_handles = drm_malloc_ab(exbuf->num_bo_handles, + sizeof(uint32_t)); + buflist = drm_calloc_large(exbuf->num_bo_handles, + sizeof(struct ttm_validate_buffer)); + if (!bo_handles || !buflist) { + drm_free_large(bo_handles); + drm_free_large(buflist); + return -ENOMEM; + } + + user_bo_handles = (void __user *)(uintptr_t)exbuf->bo_handles; + if (copy_from_user(bo_handles, user_bo_handles, + exbuf->num_bo_handles * sizeof(uint32_t))) { + ret = -EFAULT; + drm_free_large(bo_handles); + drm_free_large(buflist); + return ret; + } + + for (i = 0; i < exbuf->num_bo_handles; i++) { + gobj = drm_gem_object_lookup(dev, + drm_file, bo_handles[i]); + if (!gobj) { + drm_free_large(bo_handles); + drm_free_large(buflist); + return -ENOENT; + } + + qobj = gem_to_virtio_gpu_obj(gobj); + buflist[i].bo = &qobj->tbo; + + list_add(&buflist[i].head, &validate_list); + } + drm_free_large(bo_handles); + } + + ret = virtio_gpu_object_list_validate(&ticket, &validate_list); + if (ret) + goto out_free; + + buf = kmalloc(exbuf->size, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out_unresv; + } + if (copy_from_user(buf, (void __user *)(uintptr_t)exbuf->command, + exbuf->size)) { + kfree(buf); + ret = -EFAULT; + goto out_unresv; + } + virtio_gpu_cmd_submit(vgdev, buf, exbuf->size, + vfpriv->ctx_id, &fence); + + ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f); + + /* fence the command bo */ + virtio_gpu_unref_list(&validate_list); + drm_free_large(buflist); + fence_put(&fence->f); + return 0; + +out_unresv: + ttm_eu_backoff_reservation(&ticket, &validate_list); +out_free: + virtio_gpu_unref_list(&validate_list); + drm_free_large(buflist); + return ret; +} + +/* + * Usage of execbuffer: + * Relocations need to take into account the full VIRTIO_GPUDrawable size. + * However, the command as passed from user space must *not* contain the initial + * VIRTIO_GPUReleaseInfo struct (first XXX bytes) + */ +static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_virtgpu_execbuffer *execbuffer = data; + return virtio_gpu_execbuffer(dev, execbuffer, file_priv); +} + + +static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct drm_virtgpu_getparam *param = data; + int value; + + switch (param->param) { + case VIRTGPU_PARAM_3D_FEATURES: + value = vgdev->has_virgl_3d == true ? 1 : 0; + break; + default: + return -EINVAL; + } + if (copy_to_user((void __user *)(unsigned long)param->value, + &value, sizeof(int))) { + return -EFAULT; + } + return 0; +} + +static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct drm_virtgpu_resource_create *rc = data; + int ret; + uint32_t res_id; + struct virtio_gpu_object *qobj; + struct drm_gem_object *obj; + uint32_t handle = 0; + uint32_t size; + struct list_head validate_list; + struct ttm_validate_buffer mainbuf; + struct virtio_gpu_fence *fence = NULL; + struct ww_acquire_ctx ticket; + struct virtio_gpu_resource_create_3d rc_3d; + + if (vgdev->has_virgl_3d == false) { + if (rc->depth > 1) + return -EINVAL; + if (rc->nr_samples > 1) + return -EINVAL; + if (rc->last_level > 1) + return -EINVAL; + if (rc->target != 2) + return -EINVAL; + if (rc->array_size > 1) + return -EINVAL; + } + + INIT_LIST_HEAD(&validate_list); + memset(&mainbuf, 0, sizeof(struct ttm_validate_buffer)); + + virtio_gpu_resource_id_get(vgdev, &res_id); + + size = rc->size; + + /* allocate a single page size object */ + if (size == 0) + size = PAGE_SIZE; + + qobj = virtio_gpu_alloc_object(dev, size, false, false); + if (IS_ERR(qobj)) { + ret = PTR_ERR(qobj); + goto fail_id; + } + obj = &qobj->gem_base; + + if (!vgdev->has_virgl_3d) { + virtio_gpu_cmd_create_resource(vgdev, res_id, rc->format, + rc->width, rc->height); + + ret = virtio_gpu_object_attach(vgdev, qobj, res_id, NULL); + } else { + /* use a gem reference since unref list undoes them */ + drm_gem_object_reference(&qobj->gem_base); + mainbuf.bo = &qobj->tbo; + list_add(&mainbuf.head, &validate_list); + + ret = virtio_gpu_object_list_validate(&ticket, &validate_list); + if (ret) { + DRM_DEBUG("failed to validate\n"); + goto fail_unref; + } + + rc_3d.resource_id = cpu_to_le32(res_id); + rc_3d.target = cpu_to_le32(rc->target); + rc_3d.format = cpu_to_le32(rc->format); + rc_3d.bind = cpu_to_le32(rc->bind); + rc_3d.width = cpu_to_le32(rc->width); + rc_3d.height = cpu_to_le32(rc->height); + rc_3d.depth = cpu_to_le32(rc->depth); + rc_3d.array_size = cpu_to_le32(rc->array_size); + rc_3d.last_level = cpu_to_le32(rc->last_level); + rc_3d.nr_samples = cpu_to_le32(rc->nr_samples); + rc_3d.flags = cpu_to_le32(rc->flags); + + virtio_gpu_cmd_resource_create_3d(vgdev, &rc_3d, NULL); + ret = virtio_gpu_object_attach(vgdev, qobj, res_id, &fence); + if (ret) { + ttm_eu_backoff_reservation(&ticket, &validate_list); + goto fail_unref; + } + ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f); + } + + qobj->hw_res_handle = res_id; + + ret = drm_gem_handle_create(file_priv, obj, &handle); + if (ret) { + + drm_gem_object_release(obj); + if (vgdev->has_virgl_3d) { + virtio_gpu_unref_list(&validate_list); + fence_put(&fence->f); + } + return ret; + } + drm_gem_object_unreference_unlocked(obj); + + rc->res_handle = res_id; /* similiar to a VM address */ + rc->bo_handle = handle; + + if (vgdev->has_virgl_3d) { + virtio_gpu_unref_list(&validate_list); + fence_put(&fence->f); + } + return 0; +fail_unref: + if (vgdev->has_virgl_3d) { + virtio_gpu_unref_list(&validate_list); + fence_put(&fence->f); + } +//fail_obj: +// drm_gem_object_handle_unreference_unlocked(obj); +fail_id: + virtio_gpu_resource_id_put(vgdev, res_id); + return ret; +} + +static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_virtgpu_resource_info *ri = data; + struct drm_gem_object *gobj = NULL; + struct virtio_gpu_object *qobj = NULL; + + gobj = drm_gem_object_lookup(dev, file_priv, ri->bo_handle); + if (gobj == NULL) + return -ENOENT; + + qobj = gem_to_virtio_gpu_obj(gobj); + + ri->size = qobj->gem_base.size; + ri->res_handle = qobj->hw_res_handle; + drm_gem_object_unreference_unlocked(gobj); + return 0; +} + +static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_fpriv *vfpriv = file->driver_priv; + struct drm_virtgpu_3d_transfer_from_host *args = data; + struct drm_gem_object *gobj = NULL; + struct virtio_gpu_object *qobj = NULL; + struct virtio_gpu_fence *fence; + int ret; + u32 offset = args->offset; + struct virtio_gpu_box box; + + if (vgdev->has_virgl_3d == false) + return -ENOSYS; + + gobj = drm_gem_object_lookup(dev, file, args->bo_handle); + if (gobj == NULL) + return -ENOENT; + + qobj = gem_to_virtio_gpu_obj(gobj); + + ret = virtio_gpu_object_reserve(qobj, false); + if (ret) + goto out; + + ret = ttm_bo_validate(&qobj->tbo, &qobj->placement, + true, false); + if (unlikely(ret)) + goto out_unres; + + convert_to_hw_box(&box, &args->box); + virtio_gpu_cmd_transfer_from_host_3d + (vgdev, qobj->hw_res_handle, + vfpriv->ctx_id, offset, args->level, + &box, &fence); + reservation_object_add_excl_fence(qobj->tbo.resv, + &fence->f); + + fence_put(&fence->f); +out_unres: + virtio_gpu_object_unreserve(qobj); +out: + drm_gem_object_unreference_unlocked(gobj); + return ret; +} + +static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_fpriv *vfpriv = file->driver_priv; + struct drm_virtgpu_3d_transfer_to_host *args = data; + struct drm_gem_object *gobj = NULL; + struct virtio_gpu_object *qobj = NULL; + struct virtio_gpu_fence *fence; + struct virtio_gpu_box box; + int ret; + u32 offset = args->offset; + + gobj = drm_gem_object_lookup(dev, file, args->bo_handle); + if (gobj == NULL) + return -ENOENT; + + qobj = gem_to_virtio_gpu_obj(gobj); + + ret = virtio_gpu_object_reserve(qobj, false); + if (ret) + goto out; + + ret = ttm_bo_validate(&qobj->tbo, &qobj->placement, + true, false); + if (unlikely(ret)) + goto out_unres; + + convert_to_hw_box(&box, &args->box); + if (!vgdev->has_virgl_3d) { + virtio_gpu_cmd_transfer_to_host_2d + (vgdev, qobj->hw_res_handle, offset, + box.w, box.h, box.x, box.y, NULL); + } else { + virtio_gpu_cmd_transfer_to_host_3d + (vgdev, qobj->hw_res_handle, + vfpriv ? vfpriv->ctx_id : 0, offset, + args->level, &box, &fence); + reservation_object_add_excl_fence(qobj->tbo.resv, + &fence->f); + fence_put(&fence->f); + } + +out_unres: + virtio_gpu_object_unreserve(qobj); +out: + drm_gem_object_unreference_unlocked(gobj); + return ret; +} + +static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_virtgpu_3d_wait *args = data; + struct drm_gem_object *gobj = NULL; + struct virtio_gpu_object *qobj = NULL; + int ret; + bool nowait = false; + + gobj = drm_gem_object_lookup(dev, file, args->handle); + if (gobj == NULL) + return -ENOENT; + + qobj = gem_to_virtio_gpu_obj(gobj); + + if (args->flags & VIRTGPU_WAIT_NOWAIT) + nowait = true; + ret = virtio_gpu_object_wait(qobj, nowait); + + drm_gem_object_unreference_unlocked(gobj); + return ret; +} + +static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, + void *data, struct drm_file *file) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct drm_virtgpu_get_caps *args = data; + int size; + int i; + int found_valid = -1; + int ret; + struct virtio_gpu_drv_cap_cache *cache_ent; + void *ptr; + if (vgdev->num_capsets == 0) + return -ENOSYS; + + spin_lock(&vgdev->display_info_lock); + for (i = 0; i < vgdev->num_capsets; i++) { + if (vgdev->capsets[i].id == args->cap_set_id) { + if (vgdev->capsets[i].max_version >= args->cap_set_ver) { + found_valid = i; + break; + } + } + } + + if (found_valid == -1) { + spin_unlock(&vgdev->display_info_lock); + return -EINVAL; + } + + size = vgdev->capsets[found_valid].max_size; + if (args->size > size) { + spin_unlock(&vgdev->display_info_lock); + return -EINVAL; + } + + list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { + if (cache_ent->id == args->cap_set_id && + cache_ent->version == args->cap_set_ver) { + ptr = cache_ent->caps_cache; + spin_unlock(&vgdev->display_info_lock); + goto copy_exit; + } + } + spin_unlock(&vgdev->display_info_lock); + + /* not in cache - need to talk to hw */ + virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver, + &cache_ent); + + ret = wait_event_timeout(vgdev->resp_wq, + atomic_read(&cache_ent->is_valid), 5 * HZ); + + ptr = cache_ent->caps_cache; + +copy_exit: + if (copy_to_user((void __user *)(unsigned long)args->addr, ptr, size)) + return -EFAULT; + + return 0; +} + +struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { + DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, + DRM_AUTH|DRM_UNLOCKED), + + DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, + DRM_AUTH|DRM_UNLOCKED), + + DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, + DRM_AUTH|DRM_UNLOCKED), + + DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, + virtio_gpu_resource_create_ioctl, + DRM_AUTH|DRM_UNLOCKED), + + DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, + DRM_AUTH|DRM_UNLOCKED), + + /* make transfer async to the main ring? - no sure, can we + thread these in the underlying GL */ + DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, + virtio_gpu_transfer_from_host_ioctl, + DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, + virtio_gpu_transfer_to_host_ioctl, + DRM_AUTH|DRM_UNLOCKED), + + DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, + DRM_AUTH|DRM_UNLOCKED), + + DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, + DRM_AUTH|DRM_UNLOCKED), +}; diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 782766c00d70..06496a128162 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -52,6 +52,41 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work) events_clear, &events_clear); } +static void virtio_gpu_ctx_id_get(struct virtio_gpu_device *vgdev, + uint32_t *resid) +{ + int handle; + + idr_preload(GFP_KERNEL); + spin_lock(&vgdev->ctx_id_idr_lock); + handle = idr_alloc(&vgdev->ctx_id_idr, NULL, 1, 0, 0); + spin_unlock(&vgdev->ctx_id_idr_lock); + idr_preload_end(); + *resid = handle; +} + +static void virtio_gpu_ctx_id_put(struct virtio_gpu_device *vgdev, uint32_t id) +{ + spin_lock(&vgdev->ctx_id_idr_lock); + idr_remove(&vgdev->ctx_id_idr, id); + spin_unlock(&vgdev->ctx_id_idr_lock); +} + +static void virtio_gpu_context_create(struct virtio_gpu_device *vgdev, + uint32_t nlen, const char *name, + uint32_t *ctx_id) +{ + virtio_gpu_ctx_id_get(vgdev, ctx_id); + virtio_gpu_cmd_context_create(vgdev, *ctx_id, nlen, name); +} + +static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev, + uint32_t ctx_id) +{ + virtio_gpu_cmd_context_destroy(vgdev, ctx_id); + virtio_gpu_ctx_id_put(vgdev, ctx_id); +} + static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq, void (*work_func)(struct work_struct *work)) { @@ -60,6 +95,36 @@ static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq, INIT_WORK(&vgvq->dequeue_work, work_func); } +static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev, + int num_capsets) +{ + int i, ret; + + vgdev->capsets = kcalloc(num_capsets, + sizeof(struct virtio_gpu_drv_capset), + GFP_KERNEL); + if (!vgdev->capsets) { + DRM_ERROR("failed to allocate cap sets\n"); + return; + } + for (i = 0; i < num_capsets; i++) { + virtio_gpu_cmd_get_capset_info(vgdev, i); + ret = wait_event_timeout(vgdev->resp_wq, + vgdev->capsets[i].id > 0, 5 * HZ); + if (ret == 0) { + DRM_ERROR("timed out waiting for cap set %d\n", i); + kfree(vgdev->capsets); + vgdev->capsets = NULL; + return; + } + DRM_INFO("cap set %d: id %d, max-version %d, max-size %d\n", + i, vgdev->capsets[i].id, + vgdev->capsets[i].max_version, + vgdev->capsets[i].max_size); + } + vgdev->num_capsets = num_capsets; +} + int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) { static vq_callback_t *callbacks[] = { @@ -70,7 +135,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) struct virtio_gpu_device *vgdev; /* this will expand later */ struct virtqueue *vqs[2]; - u32 num_scanouts; + u32 num_scanouts, num_capsets; int ret; if (!virtio_has_feature(dev->virtdev, VIRTIO_F_VERSION_1)) @@ -96,9 +161,15 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&vgdev->fence_drv.lock); INIT_LIST_HEAD(&vgdev->fence_drv.fences); + INIT_LIST_HEAD(&vgdev->cap_cache); INIT_WORK(&vgdev->config_changed_work, virtio_gpu_config_changed_work_func); + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_VIRGL)) + vgdev->has_virgl_3d = true; + DRM_INFO("virgl 3d acceleration %s\n", + vgdev->has_virgl_3d ? "enabled" : "not available"); + ret = vgdev->vdev->config->find_vqs(vgdev->vdev, 2, vqs, callbacks, names); if (ret) { @@ -129,6 +200,11 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) ret = -EINVAL; goto err_scanouts; } + DRM_INFO("number of scanouts: %d\n", num_scanouts); + + virtio_cread(vgdev->vdev, struct virtio_gpu_config, + num_capsets, &num_capsets); + DRM_INFO("number of cap sets: %d\n", num_capsets); ret = virtio_gpu_modeset_init(vgdev); if (ret) @@ -137,6 +213,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) virtio_device_ready(vgdev->vdev); vgdev->vqs_ready = true; + if (num_capsets) + virtio_gpu_get_capsets(vgdev, num_capsets); virtio_gpu_cmd_get_display_info(vgdev); wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, 5 * HZ); @@ -157,6 +235,16 @@ err_vqs: return ret; } +static void virtio_gpu_cleanup_cap_cache(struct virtio_gpu_device *vgdev) +{ + struct virtio_gpu_drv_cap_cache *cache_ent, *tmp; + + list_for_each_entry_safe(cache_ent, tmp, &vgdev->cap_cache, head) { + kfree(cache_ent->caps_cache); + kfree(cache_ent); + } +} + int virtio_gpu_driver_unload(struct drm_device *dev) { struct virtio_gpu_device *vgdev = dev->dev_private; @@ -170,6 +258,49 @@ int virtio_gpu_driver_unload(struct drm_device *dev) virtio_gpu_modeset_fini(vgdev); virtio_gpu_ttm_fini(vgdev); virtio_gpu_free_vbufs(vgdev); + virtio_gpu_cleanup_cap_cache(vgdev); + kfree(vgdev->capsets); kfree(vgdev); return 0; } + +int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_fpriv *vfpriv; + uint32_t id; + char dbgname[64], tmpname[TASK_COMM_LEN]; + + /* can't create contexts without 3d renderer */ + if (!vgdev->has_virgl_3d) + return 0; + + get_task_comm(tmpname, current); + snprintf(dbgname, sizeof(dbgname), "%s", tmpname); + dbgname[63] = 0; + /* allocate a virt GPU context for this opener */ + vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL); + if (!vfpriv) + return -ENOMEM; + + virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id); + + vfpriv->ctx_id = id; + file->driver_priv = vfpriv; + return 0; +} + +void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file) +{ + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_fpriv *vfpriv; + + if (!vgdev->has_virgl_3d) + return; + + vfpriv = file->driver_priv; + + virtio_gpu_context_destroy(vgdev, vfpriv->ctx_id); + kfree(vfpriv); + file->driver_priv = NULL; +} diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index b092d7b9a292..9fd924cd2b7f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "virtgpu_drv.h" #include diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index ee25e9a4ae03..5a0f8a745b9d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -586,6 +586,47 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev, drm_kms_helper_hotplug_event(vgdev->ddev); } +static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf) +{ + struct virtio_gpu_get_capset_info *cmd = + (struct virtio_gpu_get_capset_info *)vbuf->buf; + struct virtio_gpu_resp_capset_info *resp = + (struct virtio_gpu_resp_capset_info *)vbuf->resp_buf; + int i = le32_to_cpu(cmd->capset_index); + + spin_lock(&vgdev->display_info_lock); + vgdev->capsets[i].id = le32_to_cpu(resp->capset_id); + vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version); + vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size); + spin_unlock(&vgdev->display_info_lock); + wake_up(&vgdev->resp_wq); +} + +static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf) +{ + struct virtio_gpu_get_capset *cmd = + (struct virtio_gpu_get_capset *)vbuf->buf; + struct virtio_gpu_resp_capset *resp = + (struct virtio_gpu_resp_capset *)vbuf->resp_buf; + struct virtio_gpu_drv_cap_cache *cache_ent; + + spin_lock(&vgdev->display_info_lock); + list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { + if (cache_ent->version == le32_to_cpu(cmd->capset_version) && + cache_ent->id == le32_to_cpu(cmd->capset_id)) { + memcpy(cache_ent->caps_cache, resp->capset_data, + cache_ent->size); + atomic_set(&cache_ent->is_valid, 1); + break; + } + } + spin_unlock(&vgdev->display_info_lock); + wake_up(&vgdev->resp_wq); +} + + int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) { struct virtio_gpu_ctrl_hdr *cmd_p; @@ -609,6 +650,230 @@ int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) return 0; } +int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx) +{ + struct virtio_gpu_get_capset_info *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + void *resp_buf; + + resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset_info), + GFP_KERNEL); + if (!resp_buf) + return -ENOMEM; + + cmd_p = virtio_gpu_alloc_cmd_resp + (vgdev, &virtio_gpu_cmd_get_capset_info_cb, &vbuf, + sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_capset_info), + resp_buf); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET_INFO); + cmd_p->capset_index = cpu_to_le32(idx); + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + return 0; +} + +int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, + int idx, int version, + struct virtio_gpu_drv_cap_cache **cache_p) +{ + struct virtio_gpu_get_capset *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + int max_size = vgdev->capsets[idx].max_size; + struct virtio_gpu_drv_cap_cache *cache_ent; + void *resp_buf; + + if (idx > vgdev->num_capsets) + return -EINVAL; + + if (version > vgdev->capsets[idx].max_version) + return -EINVAL; + + cache_ent = kzalloc(sizeof(*cache_ent), GFP_KERNEL); + if (!cache_ent) + return -ENOMEM; + + cache_ent->caps_cache = kmalloc(max_size, GFP_KERNEL); + if (!cache_ent->caps_cache) { + kfree(cache_ent); + return -ENOMEM; + } + + resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset) + max_size, + GFP_KERNEL); + if (!resp_buf) { + kfree(cache_ent->caps_cache); + kfree(cache_ent); + return -ENOMEM; + } + + cache_ent->version = version; + cache_ent->id = vgdev->capsets[idx].id; + atomic_set(&cache_ent->is_valid, 0); + cache_ent->size = max_size; + spin_lock(&vgdev->display_info_lock); + list_add_tail(&cache_ent->head, &vgdev->cap_cache); + spin_unlock(&vgdev->display_info_lock); + + cmd_p = virtio_gpu_alloc_cmd_resp + (vgdev, &virtio_gpu_cmd_capset_cb, &vbuf, sizeof(*cmd_p), + sizeof(struct virtio_gpu_resp_capset) + max_size, + resp_buf); + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET); + cmd_p->capset_id = cpu_to_le32(vgdev->capsets[idx].id); + cmd_p->capset_version = cpu_to_le32(version); + *cache_p = cache_ent; + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + + return 0; +} + +void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, + uint32_t nlen, const char *name) +{ + struct virtio_gpu_ctx_create *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE); + cmd_p->hdr.ctx_id = cpu_to_le32(id); + cmd_p->nlen = cpu_to_le32(nlen); + strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name)-1); + cmd_p->debug_name[sizeof(cmd_p->debug_name)-1] = 0; + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); +} + +void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev, + uint32_t id) +{ + struct virtio_gpu_ctx_destroy *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DESTROY); + cmd_p->hdr.ctx_id = cpu_to_le32(id); + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); +} + +void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev, + uint32_t ctx_id, + uint32_t resource_id) +{ + struct virtio_gpu_ctx_resource *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE); + cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id); + cmd_p->resource_id = cpu_to_le32(resource_id); + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + +} + +void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev, + uint32_t ctx_id, + uint32_t resource_id) +{ + struct virtio_gpu_ctx_resource *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE); + cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id); + cmd_p->resource_id = cpu_to_le32(resource_id); + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); +} + +void +virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev, + struct virtio_gpu_resource_create_3d *rc_3d, + struct virtio_gpu_fence **fence) +{ + struct virtio_gpu_resource_create_3d *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + *cmd_p = *rc_3d; + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D); + cmd_p->hdr.flags = 0; + + virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence); +} + +void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, + uint32_t resource_id, uint32_t ctx_id, + uint64_t offset, uint32_t level, + struct virtio_gpu_box *box, + struct virtio_gpu_fence **fence) +{ + struct virtio_gpu_transfer_host_3d *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D); + cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id); + cmd_p->resource_id = cpu_to_le32(resource_id); + cmd_p->box = *box; + cmd_p->offset = cpu_to_le64(offset); + cmd_p->level = cpu_to_le32(level); + + virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence); +} + +void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev, + uint32_t resource_id, uint32_t ctx_id, + uint64_t offset, uint32_t level, + struct virtio_gpu_box *box, + struct virtio_gpu_fence **fence) +{ + struct virtio_gpu_transfer_host_3d *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D); + cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id); + cmd_p->resource_id = cpu_to_le32(resource_id); + cmd_p->box = *box; + cmd_p->offset = cpu_to_le64(offset); + cmd_p->level = cpu_to_le32(level); + + virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence); +} + +void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev, + void *data, uint32_t data_size, + uint32_t ctx_id, struct virtio_gpu_fence **fence) +{ + struct virtio_gpu_cmd_submit *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + vbuf->data_buf = data; + vbuf->data_size = data_size; + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SUBMIT_3D); + cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id); + cmd_p->size = cpu_to_le32(data_size); + + virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence); +} + int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *obj, uint32_t resource_id, diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild index 2d9a25daab05..38d437096c35 100644 --- a/include/uapi/drm/Kbuild +++ b/include/uapi/drm/Kbuild @@ -17,3 +17,4 @@ header-y += tegra_drm.h header-y += via_drm.h header-y += vmwgfx_drm.h header-y += msm_drm.h +header-y += virtgpu_drm.h diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h new file mode 100644 index 000000000000..fc9e2d6e5e2f --- /dev/null +++ b/include/uapi/drm/virtgpu_drm.h @@ -0,0 +1,167 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRTGPU_DRM_H +#define VIRTGPU_DRM_H + +#include +#include "drm/drm.h" + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use uint64_t instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define DRM_VIRTGPU_MAP 0x01 +#define DRM_VIRTGPU_EXECBUFFER 0x02 +#define DRM_VIRTGPU_GETPARAM 0x03 +#define DRM_VIRTGPU_RESOURCE_CREATE 0x04 +#define DRM_VIRTGPU_RESOURCE_INFO 0x05 +#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x06 +#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07 +#define DRM_VIRTGPU_WAIT 0x08 +#define DRM_VIRTGPU_GET_CAPS 0x09 + +struct drm_virtgpu_map { + uint64_t offset; /* use for mmap system call */ + uint32_t handle; + uint32_t pad; +}; + +struct drm_virtgpu_execbuffer { + uint32_t flags; /* for future use */ + uint32_t size; + uint64_t command; /* void* */ + uint64_t bo_handles; + uint32_t num_bo_handles; + uint32_t pad; +}; + +#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ + +struct drm_virtgpu_getparam { + uint64_t param; + uint64_t value; +}; + +/* NO_BO flags? NO resource flag? */ +/* resource flag for y_0_top */ +struct drm_virtgpu_resource_create { + uint32_t target; + uint32_t format; + uint32_t bind; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t array_size; + uint32_t last_level; + uint32_t nr_samples; + uint32_t flags; + uint32_t bo_handle; /* if this is set - recreate a new resource attached to this bo ? */ + uint32_t res_handle; /* returned by kernel */ + uint32_t size; /* validate transfer in the host */ + uint32_t stride; /* validate transfer in the host */ +}; + +struct drm_virtgpu_resource_info { + uint32_t bo_handle; + uint32_t res_handle; + uint32_t size; + uint32_t stride; +}; + +struct drm_virtgpu_3d_box { + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t w; + uint32_t h; + uint32_t d; +}; + +struct drm_virtgpu_3d_transfer_to_host { + uint32_t bo_handle; + struct drm_virtgpu_3d_box box; + uint32_t level; + uint32_t offset; +}; + +struct drm_virtgpu_3d_transfer_from_host { + uint32_t bo_handle; + struct drm_virtgpu_3d_box box; + uint32_t level; + uint32_t offset; +}; + +#define VIRTGPU_WAIT_NOWAIT 1 /* like it */ +struct drm_virtgpu_3d_wait { + uint32_t handle; /* 0 is an invalid handle */ + uint32_t flags; +}; + +struct drm_virtgpu_get_caps { + uint32_t cap_set_id; + uint32_t cap_set_ver; + uint64_t addr; + uint32_t size; + uint32_t pad; +}; + +#define DRM_IOCTL_VIRTGPU_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) + +#define DRM_IOCTL_VIRTGPU_EXECBUFFER \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER,\ + struct drm_virtgpu_execbuffer) + +#define DRM_IOCTL_VIRTGPU_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM,\ + struct drm_virtgpu_getparam) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE, \ + struct drm_virtgpu_resource_create) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \ + struct drm_virtgpu_resource_info) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST, \ + struct drm_virtgpu_3d_transfer_from_host) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_TO_HOST, \ + struct drm_virtgpu_3d_transfer_to_host) + +#define DRM_IOCTL_VIRTGPU_WAIT \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WAIT, \ + struct drm_virtgpu_3d_wait) + +#define DRM_IOCTL_VIRTGPU_GET_CAPS \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \ + struct drm_virtgpu_get_caps) + +#endif diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h index 478be5270e26..7a63faa9065c 100644 --- a/include/uapi/linux/virtio_gpu.h +++ b/include/uapi/linux/virtio_gpu.h @@ -40,6 +40,8 @@ #include +#define VIRTIO_GPU_F_VIRGL 0 + enum virtio_gpu_ctrl_type { VIRTIO_GPU_UNDEFINED = 0, @@ -52,6 +54,18 @@ enum virtio_gpu_ctrl_type { VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D, VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING, VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, + VIRTIO_GPU_CMD_GET_CAPSET_INFO, + VIRTIO_GPU_CMD_GET_CAPSET, + + /* 3d commands */ + VIRTIO_GPU_CMD_CTX_CREATE = 0x0200, + VIRTIO_GPU_CMD_CTX_DESTROY, + VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE, + VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE, + VIRTIO_GPU_CMD_RESOURCE_CREATE_3D, + VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D, + VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D, + VIRTIO_GPU_CMD_SUBMIT_3D, /* cursor commands */ VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300, @@ -60,6 +74,8 @@ enum virtio_gpu_ctrl_type { /* success responses */ VIRTIO_GPU_RESP_OK_NODATA = 0x1100, VIRTIO_GPU_RESP_OK_DISPLAY_INFO, + VIRTIO_GPU_RESP_OK_CAPSET_INFO, + VIRTIO_GPU_RESP_OK_CAPSET, /* error responses */ VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, @@ -180,13 +196,107 @@ struct virtio_gpu_resp_display_info { } pmodes[VIRTIO_GPU_MAX_SCANOUTS]; }; +/* data passed in the control vq, 3d related */ + +struct virtio_gpu_box { + __le32 x, y, z; + __le32 w, h, d; +}; + +/* VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D, VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D */ +struct virtio_gpu_transfer_host_3d { + struct virtio_gpu_ctrl_hdr hdr; + struct virtio_gpu_box box; + __le64 offset; + __le32 resource_id; + __le32 level; + __le32 stride; + __le32 layer_stride; +}; + +/* VIRTIO_GPU_CMD_RESOURCE_CREATE_3D */ +#define VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP (1 << 0) +struct virtio_gpu_resource_create_3d { + struct virtio_gpu_ctrl_hdr hdr; + __le32 resource_id; + __le32 target; + __le32 format; + __le32 bind; + __le32 width; + __le32 height; + __le32 depth; + __le32 array_size; + __le32 last_level; + __le32 nr_samples; + __le32 flags; + __le32 padding; +}; + +/* VIRTIO_GPU_CMD_CTX_CREATE */ +struct virtio_gpu_ctx_create { + struct virtio_gpu_ctrl_hdr hdr; + __le32 nlen; + __le32 padding; + char debug_name[64]; +}; + +/* VIRTIO_GPU_CMD_CTX_DESTROY */ +struct virtio_gpu_ctx_destroy { + struct virtio_gpu_ctrl_hdr hdr; +}; + +/* VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE, VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE */ +struct virtio_gpu_ctx_resource { + struct virtio_gpu_ctrl_hdr hdr; + __le32 resource_id; + __le32 padding; +}; + +/* VIRTIO_GPU_CMD_SUBMIT_3D */ +struct virtio_gpu_cmd_submit { + struct virtio_gpu_ctrl_hdr hdr; + __le32 size; + __le32 padding; +}; + +#define VIRTIO_GPU_CAPSET_VIRGL 1 + +/* VIRTIO_GPU_CMD_GET_CAPSET_INFO */ +struct virtio_gpu_get_capset_info { + struct virtio_gpu_ctrl_hdr hdr; + __le32 capset_index; + __le32 padding; +}; + +/* VIRTIO_GPU_RESP_OK_CAPSET_INFO */ +struct virtio_gpu_resp_capset_info { + struct virtio_gpu_ctrl_hdr hdr; + __le32 capset_id; + __le32 capset_max_version; + __le32 capset_max_size; + __le32 padding; +}; + +/* VIRTIO_GPU_CMD_GET_CAPSET */ +struct virtio_gpu_get_capset { + struct virtio_gpu_ctrl_hdr hdr; + __le32 capset_id; + __le32 capset_version; +}; + +/* VIRTIO_GPU_RESP_OK_CAPSET */ +struct virtio_gpu_resp_capset { + struct virtio_gpu_ctrl_hdr hdr; + uint8_t capset_data[]; +}; + #define VIRTIO_GPU_EVENT_DISPLAY (1 << 0) struct virtio_gpu_config { __u32 events_read; __u32 events_clear; __u32 num_scanouts; - __u32 reserved; + __u32 num_capsets; }; /* simple formats for fbcon/X use */ -- cgit v1.2.3 From 22375f3e79b5b9e1dcbac998fd8473484d391d93 Mon Sep 17 00:00:00 2001 From: Mikko Rapeli Date: Thu, 15 Oct 2015 07:55:49 +0200 Subject: savage_drm.h: include Fixes compiler error: drm/savage_drm.h:50:24: error: array type has incomplete element type struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS + Signed-off-by: Mikko Rapeli Signed-off-by: Daniel Vetter --- include/uapi/drm/savage_drm.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/uapi/drm') diff --git a/include/uapi/drm/savage_drm.h b/include/uapi/drm/savage_drm.h index 818d49be2e6e..9dc9dc1a7753 100644 --- a/include/uapi/drm/savage_drm.h +++ b/include/uapi/drm/savage_drm.h @@ -26,6 +26,8 @@ #ifndef __SAVAGE_DRM_H__ #define __SAVAGE_DRM_H__ +#include + #ifndef __SAVAGE_SAREA_DEFINES__ #define __SAVAGE_SAREA_DEFINES__ -- cgit v1.2.3 From 0aa4a4b8200c9e47021e8bd2d54b3d20ca407640 Mon Sep 17 00:00:00 2001 From: Mikko Rapeli Date: Thu, 15 Oct 2015 07:55:46 +0200 Subject: r128_drm.h: include drm/drm.h Fixes compile error: drm/r128_drm.h:156:23: error: array type has incomplete element type struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS]; Signed-off-by: Mikko Rapeli Signed-off-by: Daniel Vetter --- include/uapi/drm/r128_drm.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/uapi/drm') diff --git a/include/uapi/drm/r128_drm.h b/include/uapi/drm/r128_drm.h index 8d8878b55f55..76b0aa3e8210 100644 --- a/include/uapi/drm/r128_drm.h +++ b/include/uapi/drm/r128_drm.h @@ -33,6 +33,8 @@ #ifndef __R128_DRM_H__ #define __R128_DRM_H__ +#include + /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (r128_sarea.h) */ -- cgit v1.2.3 From 70d994704e2c93a3d6be1de0c9f103fc7c186022 Mon Sep 17 00:00:00 2001 From: Mikko Rapeli Date: Thu, 15 Oct 2015 07:55:51 +0200 Subject: drm/i810_drm.h: include drm/drm.h Fixes userspace compilation error: error: array type has incomplete element type struct drm_clip_rect boxes[I810_NR_SAREA_CLIPRECTS]; Signed-off-by: Mikko Rapeli Signed-off-by: Daniel Vetter --- include/uapi/drm/i810_drm.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/uapi/drm') diff --git a/include/uapi/drm/i810_drm.h b/include/uapi/drm/i810_drm.h index 7a10bb6f2c0f..34736efd5824 100644 --- a/include/uapi/drm/i810_drm.h +++ b/include/uapi/drm/i810_drm.h @@ -1,6 +1,8 @@ #ifndef _I810_DRM_H_ #define _I810_DRM_H_ +#include + /* WARNING: These defines must be the same as what the Xserver uses. * if you change them, you must change the defines in the Xserver. */ -- cgit v1.2.3 From 39bb0c92829ad9d7525fa809aa89fc411c85a2c2 Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Thu, 8 Oct 2015 16:31:43 -0400 Subject: drm/amdgpu: update the core VI support for Stoney Add core VI enablement for Stoney. Signed-off-by: Samuel Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++- drivers/gpu/drm/amd/amdgpu/vi.c | 36 +++++++++++++++++++++++++----- include/uapi/drm/amdgpu_drm.h | 2 +- 3 files changed, 34 insertions(+), 7 deletions(-) (limited to 'include/uapi/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 645690bcb4b3..d5b421330145 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1166,7 +1166,8 @@ static int amdgpu_early_init(struct amdgpu_device *adev) case CHIP_TONGA: case CHIP_FIJI: case CHIP_CARRIZO: - if (adev->asic_type == CHIP_CARRIZO) + case CHIP_STONEY: + if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY) adev->family = AMDGPU_FAMILY_CZ; else adev->family = AMDGPU_FAMILY_VI; diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index b55ceb14fdcd..9904761c9c37 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -232,6 +232,13 @@ static const u32 cz_mgcg_cgcg_init[] = mmHDP_XDP_CGTT_BLK_CTRL, 0xc0000fff, 0x00000104, }; +static const u32 stoney_mgcg_cgcg_init[] = +{ + mmCGTT_DRM_CLK_CTRL0, 0xffffffff, 0x00000100, + mmHDP_XDP_CGTT_BLK_CTRL, 0xffffffff, 0x00000104, + mmHDP_HOST_PATH_CNTL, 0xffffffff, 0x0f000027, +}; + static void vi_init_golden_registers(struct amdgpu_device *adev) { /* Some of the registers might be dependent on GRBM_GFX_INDEX */ @@ -258,6 +265,11 @@ static void vi_init_golden_registers(struct amdgpu_device *adev) cz_mgcg_cgcg_init, (const u32)ARRAY_SIZE(cz_mgcg_cgcg_init)); break; + case CHIP_STONEY: + amdgpu_program_register_sequence(adev, + stoney_mgcg_cgcg_init, + (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init)); + break; default: break; } @@ -488,6 +500,7 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num, case CHIP_FIJI: case CHIP_TONGA: case CHIP_CARRIZO: + case CHIP_STONEY: asic_register_table = cz_allowed_read_registers; size = ARRAY_SIZE(cz_allowed_read_registers); break; @@ -543,8 +556,10 @@ static void vi_print_gpu_status_regs(struct amdgpu_device *adev) RREG32(mmSRBM_STATUS2)); dev_info(adev->dev, " SDMA0_STATUS_REG = 0x%08X\n", RREG32(mmSDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET)); - dev_info(adev->dev, " SDMA1_STATUS_REG = 0x%08X\n", - RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET)); + if (adev->sdma.num_instances > 1) { + dev_info(adev->dev, " SDMA1_STATUS_REG = 0x%08X\n", + RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET)); + } dev_info(adev->dev, " CP_STAT = 0x%08x\n", RREG32(mmCP_STAT)); dev_info(adev->dev, " CP_STALLED_STAT1 = 0x%08x\n", RREG32(mmCP_STALLED_STAT1)); @@ -639,9 +654,11 @@ u32 vi_gpu_check_soft_reset(struct amdgpu_device *adev) reset_mask |= AMDGPU_RESET_DMA; /* SDMA1_STATUS_REG */ - tmp = RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET); - if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK)) - reset_mask |= AMDGPU_RESET_DMA1; + if (adev->sdma.num_instances > 1) { + tmp = RREG32(mmSDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET); + if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK)) + reset_mask |= AMDGPU_RESET_DMA1; + } #if 0 /* VCE_STATUS */ if (adev->asic_type != CHIP_TOPAZ) { @@ -1316,6 +1333,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks); break; case CHIP_CARRIZO: + case CHIP_STONEY: adev->ip_blocks = cz_ip_blocks; adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks); break; @@ -1327,11 +1345,18 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) return 0; } +#define ATI_REV_ID_FUSE_MACRO__ADDRESS 0xC0014044 +#define ATI_REV_ID_FUSE_MACRO__SHIFT 9 +#define ATI_REV_ID_FUSE_MACRO__MASK 0x00001E00 + static uint32_t vi_get_rev_id(struct amdgpu_device *adev) { if (adev->asic_type == CHIP_TOPAZ) return (RREG32(mmPCIE_EFUSE4) & PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID_MASK) >> PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID__SHIFT; + else if (adev->flags & AMD_IS_APU) + return (RREG32_SMC(ATI_REV_ID_FUSE_MACRO__ADDRESS) & ATI_REV_ID_FUSE_MACRO__MASK) + >> ATI_REV_ID_FUSE_MACRO__SHIFT; else return (RREG32(mmCC_DRM_ID_STRAPS) & CC_DRM_ID_STRAPS__ATI_REV_ID_MASK) >> CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT; @@ -1398,6 +1423,7 @@ static int vi_common_early_init(void *handle) adev->firmware.smu_load = true; break; case CHIP_CARRIZO: + case CHIP_STONEY: adev->has_uvd = true; adev->cg_flags = 0; /* Disable UVD pg */ diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index fbdd11851725..e52933a73580 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -640,6 +640,6 @@ struct drm_amdgpu_info_hw_ip { #define AMDGPU_FAMILY_CI 120 /* Bonaire, Hawaii */ #define AMDGPU_FAMILY_KV 125 /* Kaveri, Kabini, Mullins */ #define AMDGPU_FAMILY_VI 130 /* Iceland, Tonga */ -#define AMDGPU_FAMILY_CZ 135 /* Carrizo */ +#define AMDGPU_FAMILY_CZ 135 /* Carrizo, Stoney */ #endif -- cgit v1.2.3 From fcf3f91c34105c3551741febbfc1066aaa7f1db7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 4 Sep 2015 14:40:32 +1000 Subject: drm/nouveau: remove unnecessary usage of object handles No longer required in a lot of cases, as objects are identified over NVIF via an alternate mechanism since the rework. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_abi16.c | 17 +++++------------ drivers/gpu/drm/nouveau/nouveau_chan.c | 30 +++++++++++++----------------- drivers/gpu/drm/nouveau/nouveau_chan.h | 3 +-- drivers/gpu/drm/nouveau/nouveau_display.c | 5 ++--- drivers/gpu/drm/nouveau/nouveau_drm.c | 10 ++++------ drivers/gpu/drm/nouveau/nouveau_drm.h | 5 ----- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/gpu/drm/nouveau/nouveau_sysfs.c | 5 ++--- drivers/gpu/drm/nouveau/nv50_display.c | 7 +++---- include/uapi/drm/nouveau_drm.h | 8 -------- 10 files changed, 31 insertions(+), 61 deletions(-) (limited to 'include/uapi/drm') diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index d336c2247d6a..0b3c8abd6843 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -51,8 +51,7 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) * device (ie. the one that belongs to the fd it * opened) */ - if (nvif_device_init(&cli->base.object, - NOUVEAU_ABI16_DEVICE, NV_DEVICE, + if (nvif_device_init(&cli->base.object, 0, NV_DEVICE, &args, sizeof(args), &abi16->device) == 0) return cli->abi16; @@ -133,7 +132,6 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, /* destroy channel object, all children will be killed too */ if (chan->chan) { - abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff)); nouveau_channel_idle(chan->chan); nouveau_channel_del(&chan->chan); } @@ -268,26 +266,21 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) return nouveau_abi16_put(abi16, -EINVAL); /* allocate "abi16 channel" data and make up a handle for it */ - init->channel = __ffs64(~abi16->handles); - if (~abi16->handles == 0) - return nouveau_abi16_put(abi16, -ENOSPC); - chan = kzalloc(sizeof(*chan), GFP_KERNEL); if (!chan) return nouveau_abi16_put(abi16, -ENOMEM); INIT_LIST_HEAD(&chan->notifiers); list_add(&chan->head, &abi16->channels); - abi16->handles |= (1ULL << init->channel); /* create channel object and initialise dma and fence management */ - ret = nouveau_channel_new(drm, device, - NOUVEAU_ABI16_CHAN(init->channel), - init->fb_ctxdma_handle, + ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle, init->tt_ctxdma_handle, &chan->chan); if (ret) goto done; + init->channel = chan->chan->chid; + if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART; @@ -338,7 +331,7 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel) struct nouveau_abi16_chan *chan; list_for_each_entry(chan, &abi16->channels, head) { - if (chan->chan->user.handle == NOUVEAU_ABI16_CHAN(channel)) + if (chan->chan->chid == channel) return chan; } diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index ff5e59db49db..1860f389f21f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -55,10 +55,8 @@ nouveau_channel_idle(struct nouveau_channel *chan) } if (ret) { - NV_PRINTK(err, cli, "failed to idle channel " - "0x%08x [%s]\n", - chan->user.handle, - nvxx_client(&cli->base)->name); + NV_PRINTK(err, cli, "failed to idle channel %d [%s]\n", + chan->chid, nvxx_client(&cli->base)->name); return ret; } } @@ -89,7 +87,7 @@ nouveau_channel_del(struct nouveau_channel **pchan) static int nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, u32 size, struct nouveau_channel **pchan) + u32 size, struct nouveau_channel **pchan) { struct nouveau_cli *cli = (void *)device->object.client; struct nvkm_mmu *mmu = nvxx_mmu(device); @@ -174,8 +172,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, } } - ret = nvif_object_init(&device->object, NVDRM_PUSH | - (handle & 0xffff), NV_DMA_FROM_MEMORY, + ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY, &args, sizeof(args), &chan->push.ctxdma); if (ret) { nouveau_channel_del(pchan); @@ -187,7 +184,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, static int nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, u32 engine, struct nouveau_channel **pchan) + u32 engine, struct nouveau_channel **pchan) { static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A, KEPLER_CHANNEL_GPFIFO_A, @@ -206,7 +203,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, int ret; /* allocate dma push buffer */ - ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan); + ret = nouveau_channel_prep(drm, device, 0x12000, &chan); *pchan = chan; if (ret) return ret; @@ -236,7 +233,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, size = sizeof(args.nv50); } - ret = nvif_object_init(&device->object, handle, *oclass++, + ret = nvif_object_init(&device->object, 0, *oclass++, &args, size, &chan->user); if (ret == 0) { if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) @@ -256,7 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, static int nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, struct nouveau_channel **pchan) + struct nouveau_channel **pchan) { static const u16 oclasses[] = { NV40_CHANNEL_DMA, NV17_CHANNEL_DMA, @@ -269,7 +266,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, int ret; /* allocate dma push buffer */ - ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan); + ret = nouveau_channel_prep(drm, device, 0x10000, &chan); *pchan = chan; if (ret) return ret; @@ -280,7 +277,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, args.offset = chan->push.vma.offset; do { - ret = nvif_object_init(&device->object, handle, *oclass++, + ret = nvif_object_init(&device->object, 0, *oclass++, &args, sizeof(args), &chan->user); if (ret == 0) { chan->chid = args.chid; @@ -401,8 +398,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) int nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, - u32 handle, u32 arg0, u32 arg1, - struct nouveau_channel **pchan) + u32 arg0, u32 arg1, struct nouveau_channel **pchan) { struct nouveau_cli *cli = (void *)device->object.client; bool super; @@ -412,10 +408,10 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, super = cli->base.super; cli->base.super = true; - ret = nouveau_channel_ind(drm, device, handle, arg0, pchan); + ret = nouveau_channel_ind(drm, device, arg0, pchan); if (ret) { NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); - ret = nouveau_channel_dma(drm, device, handle, pchan); + ret = nouveau_channel_dma(drm, device, pchan); if (ret) { NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret); goto done; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 2ed32414cb69..48062c94f36d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -42,8 +42,7 @@ struct nouveau_channel { int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, - u32 handle, u32 arg0, u32 arg1, - struct nouveau_channel **); + u32 arg0, u32 arg1, struct nouveau_channel **); void nouveau_channel_del(struct nouveau_channel **); int nouveau_channel_idle(struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 614b32e6381c..db6bc6760545 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -509,9 +509,8 @@ nouveau_display_create(struct drm_device *dev) int i; for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) { - ret = nvif_object_init(&drm->device.object, - NVDRM_DISPLAY, oclass[i], - NULL, 0, &disp->disp); + ret = nvif_object_init(&drm->device.object, 0, + oclass[i], NULL, 0, &disp->disp); } if (ret == 0) { diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 45ba67819199..f93266582f27 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -208,7 +208,7 @@ nouveau_accel_init(struct nouveau_drm *drm) } if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { - ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, + ret = nouveau_channel_new(drm, &drm->device, KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0| KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1, 0, &drm->cechan); @@ -221,7 +221,7 @@ nouveau_accel_init(struct nouveau_drm *drm) if (device->info.chipset >= 0xa3 && device->info.chipset != 0xaa && device->info.chipset != 0xac) { - ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, + ret = nouveau_channel_new(drm, &drm->device, NvDmaFB, NvDmaTT, &drm->cechan); if (ret) NV_ERROR(drm, "failed to create ce channel, %d\n", ret); @@ -233,8 +233,7 @@ nouveau_accel_init(struct nouveau_drm *drm) arg1 = NvDmaTT; } - ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1, - &drm->channel); + ret = nouveau_channel_new(drm, &drm->device, arg0, arg1, &drm->channel); if (ret) { NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); nouveau_accel_fini(drm); @@ -403,8 +402,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) nouveau_get_hdmi_dev(drm); - ret = nvif_device_init(&drm->client.base.object, - NVDRM_DEVICE, NV_DEVICE, + ret = nvif_device_init(&drm->client.base.object, 0, NV_DEVICE, &(struct nv_device_v0) { .device = ~0, }, sizeof(struct nv_device_v0), diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 3c902c24a8dd..acfa03bd50de 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -74,11 +74,6 @@ enum nouveau_drm_notify_route { }; enum nouveau_drm_handle { - NVDRM_CLIENT = 0xffffffff, - NVDRM_DEVICE = 0xdddddddd, - NVDRM_CONTROL = 0xdddddddc, - NVDRM_DISPLAY = 0xd1500000, - NVDRM_PUSH = 0xbbbb0000, /* |= client chid */ NVDRM_CHAN = 0xcccc0000, /* |= client chid */ NVDRM_NVSW = 0x55550000, }; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 41be584147b9..6bf1a7895708 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -682,7 +682,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, return -ENOMEM; list_for_each_entry(temp, &abi16->channels, head) { - if (temp->chan->user.handle == (NVDRM_CHAN | req->channel)) { + if (temp->chan->chid == req->channel) { chan = temp->chan; break; } diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c index d12a5faee047..5dac3546c1b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c @@ -188,9 +188,8 @@ nouveau_sysfs_init(struct drm_device *dev) if (!sysfs) return -ENOMEM; - ret = nvif_object_init(&device->object, NVDRM_CONTROL, - NVIF_IOCTL_NEW_V0_CONTROL, NULL, 0, - &sysfs->ctrl); + ret = nvif_object_init(&device->object, 0, NVIF_IOCTL_NEW_V0_CONTROL, + NULL, 0, &sysfs->ctrl); if (ret == 0) device_create_file(nvxx_device(device)->dev, &dev_attr_pstate); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 4ae87aed4505..c053c50b346a 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -68,7 +68,6 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp, const s32 *oclass, u8 head, void *data, u32 size, struct nv50_chan *chan) { - const u32 handle = (oclass[0] << 16) | head; struct nvif_sclass *sclass; int ret, i, n; @@ -81,7 +80,7 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp, while (oclass[0]) { for (i = 0; i < n; i++) { if (sclass[i].oclass == oclass[0]) { - ret = nvif_object_init(disp, handle, oclass[0], + ret = nvif_object_init(disp, 0, oclass[0], data, size, &chan->user); if (ret == 0) nvif_object_map(&chan->user); @@ -231,8 +230,8 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, if (!dmac->ptr) return -ENOMEM; - ret = nvif_object_init(&device->object, 0xd0000000, - NV_DMA_FROM_MEMORY, &(struct nv_dma_v0) { + ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY, + &(struct nv_dma_v0) { .target = NV_DMA_V0_TARGET_PCI_US, .access = NV_DMA_V0_ACCESS_RD, .start = dmac->handle + 0x0000, diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h index 5507eead5863..fd594cc73cc0 100644 --- a/include/uapi/drm/nouveau_drm.h +++ b/include/uapi/drm/nouveau_drm.h @@ -27,14 +27,6 @@ #define DRM_NOUVEAU_EVENT_NVIF 0x80000000 -/* reserved object handles when using deprecated object APIs - these - * are here so that libdrm can allow interoperability with the new - * object APIs - */ -#define NOUVEAU_ABI16_CLIENT 0xffffffff -#define NOUVEAU_ABI16_DEVICE 0xdddddddd -#define NOUVEAU_ABI16_CHAN(n) (0xcccc0000 | (n)) - #define NOUVEAU_GEM_DOMAIN_CPU (1 << 0) #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) -- cgit v1.2.3 From 6172180c6b37ea164bf8a9bad70bb348d0a16563 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 23 Sep 2015 10:10:31 +0100 Subject: drm: Use userspace compatible type in fourcc_mod_code macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __u64 should be used instead of u64. Feature originally added in: commit e3eb3250d84ef97b766312345774367b6a310db8 Author: Rob Clark Date: Thu Feb 5 14:41:52 2015 +0000 drm: add support for tiled/compressed/etc modifier in addfb2 Signed-off-by: Tvrtko Ursulin Cc: Rob Clark Cc: Daniel Stone Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Cc: stable@vger.kernel.org # v4.1+ Fixes: e3eb3250d84e ("drm: add support for tiled/compressed/etc modifier in addfb2") Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1442999431-28568-1-git-send-email-tvrtko.ursulin@linux.intel.com Signed-off-by: Jani Nikula --- include/uapi/drm/drm_fourcc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/uapi/drm') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 8c5e8b91a3cb..0b69a7753558 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -158,7 +158,7 @@ /* add more to the end as needed */ #define fourcc_mod_code(vendor, val) \ - ((((u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL)) + ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL)) /* * Format Modifier tokens: -- cgit v1.2.3