Merge tag 'drm-misc-next-2018-11-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v4.21, part 2: UAPI Changes: - Remove syncobj timeline support from drm. Cross-subsystem Changes: - Document canvas provider node in the DT bindings. - Improve documentation for TPO TPG110 DT bindings. Core Changes: - Use explicit state in drm atomic functions. - Add panel quirk for new GPD Win2 firmware. - Add DRM_FORMAT_XYUV8888. - Set the default import/export function in prime to drm_gem_prime_import/export. - Add a separate drm_gem_object_funcs, to stop relying on dev->driver->*gem* functions. - Make sure that tinydrm sets the virtual address also on imported buffers. Driver Changes: - Support active-low data enable signal in sun4i. - Fix scaling in vc4. - Use canvas provider node in meson. - Remove unused variables in sti and qxl and cirrus. - Add overlay plane support and primary plane scaling to meson. - i2c fixes in drm/bridge/sii902x - Fix mailbox read size in rockchip. - Spelling fix in panel/s6d16d0. - Remove unnecessary null check from qxl_bo_unref. - Remove unused arguments from qxl_bo_pin. - Fix qxl cursor pinning. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/9c0409e3-a85f-d2af-b4eb-baf1eb8bbae4@linux.intel.com
This commit is contained in:
@@ -47,8 +47,8 @@
|
||||
#define DRIVER_DATE "0"
|
||||
|
||||
#define DRIVER_MAJOR 0
|
||||
#define DRIVER_MINOR 0
|
||||
#define DRIVER_PATCHLEVEL 1
|
||||
#define DRIVER_MINOR 1
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
/* virtgpu_drm_bus.c */
|
||||
int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev);
|
||||
@@ -131,6 +131,7 @@ struct virtio_gpu_framebuffer {
|
||||
int x1, y1, x2, y2; /* dirty rect */
|
||||
spinlock_t dirty_lock;
|
||||
uint32_t hw_res_handle;
|
||||
struct virtio_gpu_fence *fence;
|
||||
};
|
||||
#define to_virtio_gpu_framebuffer(x) \
|
||||
container_of(x, struct virtio_gpu_framebuffer, base)
|
||||
@@ -346,6 +347,9 @@ void virtio_gpu_ttm_fini(struct virtio_gpu_device *vgdev);
|
||||
int virtio_gpu_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
|
||||
/* virtio_gpu_fence.c */
|
||||
struct virtio_gpu_fence *virtio_gpu_fence_alloc(
|
||||
struct virtio_gpu_device *vgdev);
|
||||
void virtio_gpu_fence_cleanup(struct virtio_gpu_fence *fence);
|
||||
int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
|
||||
struct virtio_gpu_ctrl_hdr *cmd_hdr,
|
||||
struct virtio_gpu_fence **fence);
|
||||
|
@@ -67,6 +67,28 @@ static const struct dma_fence_ops virtio_fence_ops = {
|
||||
.timeline_value_str = virtio_timeline_value_str,
|
||||
};
|
||||
|
||||
struct virtio_gpu_fence *virtio_gpu_fence_alloc(struct virtio_gpu_device *vgdev)
|
||||
{
|
||||
struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
|
||||
struct virtio_gpu_fence *fence = kzalloc(sizeof(struct virtio_gpu_fence),
|
||||
GFP_ATOMIC);
|
||||
if (!fence)
|
||||
return fence;
|
||||
|
||||
fence->drv = drv;
|
||||
dma_fence_init(&fence->f, &virtio_fence_ops, &drv->lock, drv->context, 0);
|
||||
|
||||
return fence;
|
||||
}
|
||||
|
||||
void virtio_gpu_fence_cleanup(struct virtio_gpu_fence *fence)
|
||||
{
|
||||
if (!fence)
|
||||
return;
|
||||
|
||||
dma_fence_put(&fence->f);
|
||||
}
|
||||
|
||||
int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
|
||||
struct virtio_gpu_ctrl_hdr *cmd_hdr,
|
||||
struct virtio_gpu_fence **fence)
|
||||
@@ -74,15 +96,8 @@ int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
|
||||
struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
|
||||
unsigned long irq_flags;
|
||||
|
||||
*fence = kmalloc(sizeof(struct virtio_gpu_fence), GFP_ATOMIC);
|
||||
if ((*fence) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&drv->lock, irq_flags);
|
||||
(*fence)->drv = drv;
|
||||
(*fence)->seq = ++drv->sync_seq;
|
||||
dma_fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock,
|
||||
drv->context, (*fence)->seq);
|
||||
dma_fence_get(&(*fence)->f);
|
||||
list_add_tail(&(*fence)->node, &drv->fences);
|
||||
spin_unlock_irqrestore(&drv->lock, irq_flags);
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/virtgpu_drm.h>
|
||||
#include <drm/ttm/ttm_execbuf_util.h>
|
||||
#include <linux/sync_file.h>
|
||||
|
||||
#include "virtgpu_drv.h"
|
||||
|
||||
@@ -105,7 +106,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
|
||||
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_fence *out_fence;
|
||||
struct virtio_gpu_object *qobj;
|
||||
int ret;
|
||||
uint32_t *bo_handles = NULL;
|
||||
@@ -114,11 +115,46 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
|
||||
struct ttm_validate_buffer *buflist = NULL;
|
||||
int i;
|
||||
struct ww_acquire_ctx ticket;
|
||||
struct sync_file *sync_file;
|
||||
int in_fence_fd = exbuf->fence_fd;
|
||||
int out_fence_fd = -1;
|
||||
void *buf;
|
||||
|
||||
if (vgdev->has_virgl_3d == false)
|
||||
return -ENOSYS;
|
||||
|
||||
if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS))
|
||||
return -EINVAL;
|
||||
|
||||
exbuf->fence_fd = -1;
|
||||
|
||||
if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) {
|
||||
struct dma_fence *in_fence;
|
||||
|
||||
in_fence = sync_file_get_fence(in_fence_fd);
|
||||
|
||||
if (!in_fence)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Wait if the fence is from a foreign context, or if the fence
|
||||
* array contains any fence from a foreign context.
|
||||
*/
|
||||
ret = 0;
|
||||
if (!dma_fence_match_context(in_fence, vgdev->fence_drv.context))
|
||||
ret = dma_fence_wait(in_fence, true);
|
||||
|
||||
dma_fence_put(in_fence);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) {
|
||||
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
|
||||
if (out_fence_fd < 0)
|
||||
return out_fence_fd;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&validate_list);
|
||||
if (exbuf->num_bo_handles) {
|
||||
|
||||
@@ -128,26 +164,22 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
|
||||
sizeof(struct ttm_validate_buffer),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!bo_handles || !buflist) {
|
||||
kvfree(bo_handles);
|
||||
kvfree(buflist);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto out_unused_fd;
|
||||
}
|
||||
|
||||
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;
|
||||
kvfree(bo_handles);
|
||||
kvfree(buflist);
|
||||
return ret;
|
||||
goto out_unused_fd;
|
||||
}
|
||||
|
||||
for (i = 0; i < exbuf->num_bo_handles; i++) {
|
||||
gobj = drm_gem_object_lookup(drm_file, bo_handles[i]);
|
||||
if (!gobj) {
|
||||
kvfree(bo_handles);
|
||||
kvfree(buflist);
|
||||
return -ENOENT;
|
||||
ret = -ENOENT;
|
||||
goto out_unused_fd;
|
||||
}
|
||||
|
||||
qobj = gem_to_virtio_gpu_obj(gobj);
|
||||
@@ -156,6 +188,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
|
||||
list_add(&buflist[i].head, &validate_list);
|
||||
}
|
||||
kvfree(bo_handles);
|
||||
bo_handles = NULL;
|
||||
}
|
||||
|
||||
ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
|
||||
@@ -168,22 +201,48 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
|
||||
ret = PTR_ERR(buf);
|
||||
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);
|
||||
out_fence = virtio_gpu_fence_alloc(vgdev);
|
||||
if(!out_fence) {
|
||||
ret = -ENOMEM;
|
||||
goto out_memdup;
|
||||
}
|
||||
|
||||
if (out_fence_fd >= 0) {
|
||||
sync_file = sync_file_create(&out_fence->f);
|
||||
if (!sync_file) {
|
||||
dma_fence_put(&out_fence->f);
|
||||
ret = -ENOMEM;
|
||||
goto out_memdup;
|
||||
}
|
||||
|
||||
exbuf->fence_fd = out_fence_fd;
|
||||
fd_install(out_fence_fd, sync_file->file);
|
||||
}
|
||||
|
||||
virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
|
||||
vfpriv->ctx_id, &out_fence);
|
||||
|
||||
ttm_eu_fence_buffer_objects(&ticket, &validate_list, &out_fence->f);
|
||||
|
||||
/* fence the command bo */
|
||||
virtio_gpu_unref_list(&validate_list);
|
||||
kvfree(buflist);
|
||||
dma_fence_put(&fence->f);
|
||||
return 0;
|
||||
|
||||
out_memdup:
|
||||
kfree(buf);
|
||||
out_unresv:
|
||||
ttm_eu_backoff_reservation(&ticket, &validate_list);
|
||||
out_free:
|
||||
virtio_gpu_unref_list(&validate_list);
|
||||
out_unused_fd:
|
||||
kvfree(bo_handles);
|
||||
kvfree(buflist);
|
||||
|
||||
if (out_fence_fd >= 0)
|
||||
put_unused_fd(out_fence_fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -283,11 +342,17 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
|
||||
rc_3d.nr_samples = cpu_to_le32(rc->nr_samples);
|
||||
rc_3d.flags = cpu_to_le32(rc->flags);
|
||||
|
||||
fence = virtio_gpu_fence_alloc(vgdev);
|
||||
if (!fence) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_backoff;
|
||||
}
|
||||
|
||||
virtio_gpu_cmd_resource_create_3d(vgdev, qobj, &rc_3d, NULL);
|
||||
ret = virtio_gpu_object_attach(vgdev, qobj, &fence);
|
||||
if (ret) {
|
||||
ttm_eu_backoff_reservation(&ticket, &validate_list);
|
||||
goto fail_unref;
|
||||
virtio_gpu_fence_cleanup(fence);
|
||||
goto fail_backoff;
|
||||
}
|
||||
ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f);
|
||||
}
|
||||
@@ -312,6 +377,8 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
|
||||
dma_fence_put(&fence->f);
|
||||
}
|
||||
return 0;
|
||||
fail_backoff:
|
||||
ttm_eu_backoff_reservation(&ticket, &validate_list);
|
||||
fail_unref:
|
||||
if (vgdev->has_virgl_3d) {
|
||||
virtio_gpu_unref_list(&validate_list);
|
||||
@@ -374,6 +441,12 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
|
||||
goto out_unres;
|
||||
|
||||
convert_to_hw_box(&box, &args->box);
|
||||
|
||||
fence = virtio_gpu_fence_alloc(vgdev);
|
||||
if (!fence) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unres;
|
||||
}
|
||||
virtio_gpu_cmd_transfer_from_host_3d
|
||||
(vgdev, qobj->hw_res_handle,
|
||||
vfpriv->ctx_id, offset, args->level,
|
||||
@@ -423,6 +496,11 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
|
||||
(vgdev, qobj, offset,
|
||||
box.w, box.h, box.x, box.y, NULL);
|
||||
} else {
|
||||
fence = virtio_gpu_fence_alloc(vgdev);
|
||||
if (!fence) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unres;
|
||||
}
|
||||
virtio_gpu_cmd_transfer_to_host_3d
|
||||
(vgdev, qobj,
|
||||
vfpriv ? vfpriv->ctx_id : 0, offset,
|
||||
|
@@ -55,10 +55,11 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
|
||||
static int virtio_gpu_context_create(struct virtio_gpu_device *vgdev,
|
||||
uint32_t nlen, const char *name)
|
||||
{
|
||||
int handle = ida_alloc_min(&vgdev->ctx_id_ida, 1, GFP_KERNEL);
|
||||
int handle = ida_alloc(&vgdev->ctx_id_ida, GFP_KERNEL);
|
||||
|
||||
if (handle < 0)
|
||||
return handle;
|
||||
handle += 1;
|
||||
virtio_gpu_cmd_context_create(vgdev, handle, nlen, name);
|
||||
return handle;
|
||||
}
|
||||
@@ -67,7 +68,7 @@ static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev,
|
||||
uint32_t ctx_id)
|
||||
{
|
||||
virtio_gpu_cmd_context_destroy(vgdev, ctx_id);
|
||||
ida_free(&vgdev->ctx_id_ida, ctx_id);
|
||||
ida_free(&vgdev->ctx_id_ida, ctx_id - 1);
|
||||
}
|
||||
|
||||
static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
|
||||
@@ -266,8 +267,10 @@ int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
|
||||
|
||||
get_task_comm(dbgname, current);
|
||||
id = virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname);
|
||||
if (id < 0)
|
||||
if (id < 0) {
|
||||
kfree(vfpriv);
|
||||
return id;
|
||||
}
|
||||
|
||||
vfpriv->ctx_id = id;
|
||||
file->driver_priv = vfpriv;
|
||||
|
@@ -25,16 +25,21 @@
|
||||
|
||||
#include "virtgpu_drv.h"
|
||||
|
||||
static void virtio_gpu_resource_id_get(struct virtio_gpu_device *vgdev,
|
||||
static int virtio_gpu_resource_id_get(struct virtio_gpu_device *vgdev,
|
||||
uint32_t *resid)
|
||||
{
|
||||
int handle = ida_alloc_min(&vgdev->resource_ida, 1, GFP_KERNEL);
|
||||
*resid = handle;
|
||||
int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL);
|
||||
|
||||
if (handle < 0)
|
||||
return handle;
|
||||
|
||||
*resid = handle + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtio_gpu_resource_id_put(struct virtio_gpu_device *vgdev, uint32_t id)
|
||||
{
|
||||
ida_free(&vgdev->resource_ida, id);
|
||||
ida_free(&vgdev->resource_ida, id - 1);
|
||||
}
|
||||
|
||||
static void virtio_gpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
|
||||
@@ -94,7 +99,11 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
|
||||
bo = kzalloc(sizeof(struct virtio_gpu_object), GFP_KERNEL);
|
||||
if (bo == NULL)
|
||||
return -ENOMEM;
|
||||
virtio_gpu_resource_id_get(vgdev, &bo->hw_res_handle);
|
||||
ret = virtio_gpu_resource_id_get(vgdev, &bo->hw_res_handle);
|
||||
if (ret < 0) {
|
||||
kfree(bo);
|
||||
return ret;
|
||||
}
|
||||
size = roundup(size, PAGE_SIZE);
|
||||
ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, size);
|
||||
if (ret != 0) {
|
||||
|
@@ -137,6 +137,41 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
|
||||
plane->state->src_h >> 16);
|
||||
}
|
||||
|
||||
static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct virtio_gpu_device *vgdev = dev->dev_private;
|
||||
struct virtio_gpu_framebuffer *vgfb;
|
||||
struct virtio_gpu_object *bo;
|
||||
|
||||
if (!new_state->fb)
|
||||
return 0;
|
||||
|
||||
vgfb = to_virtio_gpu_framebuffer(new_state->fb);
|
||||
bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
|
||||
if (bo && bo->dumb && (plane->state->fb != new_state->fb)) {
|
||||
vgfb->fence = virtio_gpu_fence_alloc(vgdev);
|
||||
if (!vgfb->fence)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtio_gpu_cursor_cleanup_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct virtio_gpu_framebuffer *vgfb;
|
||||
|
||||
if (!plane->state->fb)
|
||||
return;
|
||||
|
||||
vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
|
||||
if (vgfb->fence)
|
||||
virtio_gpu_fence_cleanup(vgfb->fence);
|
||||
}
|
||||
|
||||
static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
@@ -144,7 +179,6 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
|
||||
struct virtio_gpu_device *vgdev = dev->dev_private;
|
||||
struct virtio_gpu_output *output = NULL;
|
||||
struct virtio_gpu_framebuffer *vgfb;
|
||||
struct virtio_gpu_fence *fence = NULL;
|
||||
struct virtio_gpu_object *bo = NULL;
|
||||
uint32_t handle;
|
||||
int ret = 0;
|
||||
@@ -170,13 +204,13 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
|
||||
(vgdev, bo, 0,
|
||||
cpu_to_le32(plane->state->crtc_w),
|
||||
cpu_to_le32(plane->state->crtc_h),
|
||||
0, 0, &fence);
|
||||
0, 0, &vgfb->fence);
|
||||
ret = virtio_gpu_object_reserve(bo, false);
|
||||
if (!ret) {
|
||||
reservation_object_add_excl_fence(bo->tbo.resv,
|
||||
&fence->f);
|
||||
dma_fence_put(&fence->f);
|
||||
fence = NULL;
|
||||
&vgfb->fence->f);
|
||||
dma_fence_put(&vgfb->fence->f);
|
||||
vgfb->fence = NULL;
|
||||
virtio_gpu_object_unreserve(bo);
|
||||
virtio_gpu_object_wait(bo, false);
|
||||
}
|
||||
@@ -218,6 +252,8 @@ static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = {
|
||||
};
|
||||
|
||||
static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = {
|
||||
.prepare_fb = virtio_gpu_cursor_prepare_fb,
|
||||
.cleanup_fb = virtio_gpu_cursor_cleanup_fb,
|
||||
.atomic_check = virtio_gpu_plane_atomic_check,
|
||||
.atomic_update = virtio_gpu_cursor_plane_update,
|
||||
};
|
||||
|
@@ -896,9 +896,9 @@ void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev,
|
||||
struct virtio_gpu_object *obj)
|
||||
{
|
||||
bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
|
||||
struct virtio_gpu_fence *fence;
|
||||
|
||||
if (use_dma_api && obj->mapped) {
|
||||
struct virtio_gpu_fence *fence = virtio_gpu_fence_alloc(vgdev);
|
||||
/* detach backing and wait for the host process it ... */
|
||||
virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, &fence);
|
||||
dma_fence_wait(&fence->f, true);
|
||||
|
Reference in New Issue
Block a user