mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-17 18:56:24 +00:00
drm/virtio: implement context init: add virtio_gpu_fence_event
Similar to DRM_VMW_EVENT_FENCE_SIGNALED. Sends a pollable event to the DRM file descriptor when a fence on a specific ring is signaled. One difference is the event is not exposed via the UAPI -- this is because host responses are on a shared memory buffer of type BLOB_MEM_GUEST [this is the common way to receive responses with virtgpu]. As such, there is no context specific read(..) implementation either -- just a poll(..) implementation. Signed-off-by: Gurchetan Singh <gurchetansingh@chromium.org> Acked-by: Nicholas Verne <nverne@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20210921232024.817-12-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
8d6b006e1f
commit
cd7f5ca335
@ -29,6 +29,8 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#include <linux/poll.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
|
||||||
#include <drm/drm.h>
|
#include <drm/drm.h>
|
||||||
#include <drm/drm_aperture.h>
|
#include <drm/drm_aperture.h>
|
||||||
@ -155,6 +157,35 @@ static void virtio_gpu_config_changed(struct virtio_device *vdev)
|
|||||||
schedule_work(&vgdev->config_changed_work);
|
schedule_work(&vgdev->config_changed_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __poll_t virtio_gpu_poll(struct file *filp,
|
||||||
|
struct poll_table_struct *wait)
|
||||||
|
{
|
||||||
|
struct drm_file *drm_file = filp->private_data;
|
||||||
|
struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv;
|
||||||
|
struct drm_device *dev = drm_file->minor->dev;
|
||||||
|
struct drm_pending_event *e = NULL;
|
||||||
|
__poll_t mask = 0;
|
||||||
|
|
||||||
|
if (!vfpriv->ring_idx_mask)
|
||||||
|
return drm_poll(filp, wait);
|
||||||
|
|
||||||
|
poll_wait(filp, &drm_file->event_wait, wait);
|
||||||
|
|
||||||
|
if (!list_empty(&drm_file->event_list)) {
|
||||||
|
spin_lock_irq(&dev->event_lock);
|
||||||
|
e = list_first_entry(&drm_file->event_list,
|
||||||
|
struct drm_pending_event, link);
|
||||||
|
drm_file->event_space += e->event->length;
|
||||||
|
list_del(&e->link);
|
||||||
|
spin_unlock_irq(&dev->event_lock);
|
||||||
|
|
||||||
|
kfree(e);
|
||||||
|
mask |= EPOLLIN | EPOLLRDNORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
static struct virtio_device_id id_table[] = {
|
static struct virtio_device_id id_table[] = {
|
||||||
{ VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID },
|
{ VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
@ -194,7 +225,17 @@ MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>");
|
|||||||
MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
|
MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
|
||||||
MODULE_AUTHOR("Alon Levy");
|
MODULE_AUTHOR("Alon Levy");
|
||||||
|
|
||||||
DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops);
|
static const struct file_operations virtio_gpu_driver_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = drm_open,
|
||||||
|
.release = drm_release,
|
||||||
|
.unlocked_ioctl = drm_ioctl,
|
||||||
|
.compat_ioctl = drm_compat_ioctl,
|
||||||
|
.poll = virtio_gpu_poll,
|
||||||
|
.read = drm_read,
|
||||||
|
.llseek = noop_llseek,
|
||||||
|
.mmap = drm_gem_mmap
|
||||||
|
};
|
||||||
|
|
||||||
static const struct drm_driver driver = {
|
static const struct drm_driver driver = {
|
||||||
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,
|
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,
|
||||||
|
@ -138,11 +138,18 @@ struct virtio_gpu_fence_driver {
|
|||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define VIRTGPU_EVENT_FENCE_SIGNALED_INTERNAL 0x10000000
|
||||||
|
struct virtio_gpu_fence_event {
|
||||||
|
struct drm_pending_event base;
|
||||||
|
struct drm_event event;
|
||||||
|
};
|
||||||
|
|
||||||
struct virtio_gpu_fence {
|
struct virtio_gpu_fence {
|
||||||
struct dma_fence f;
|
struct dma_fence f;
|
||||||
uint32_t ring_idx;
|
uint32_t ring_idx;
|
||||||
uint64_t fence_id;
|
uint64_t fence_id;
|
||||||
bool emit_fence_info;
|
bool emit_fence_info;
|
||||||
|
struct virtio_gpu_fence_event *e;
|
||||||
struct virtio_gpu_fence_driver *drv;
|
struct virtio_gpu_fence_driver *drv;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
};
|
};
|
||||||
|
@ -152,11 +152,21 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
dma_fence_signal_locked(&curr->f);
|
dma_fence_signal_locked(&curr->f);
|
||||||
|
if (curr->e) {
|
||||||
|
drm_send_event(vgdev->ddev, &curr->e->base);
|
||||||
|
curr->e = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
list_del(&curr->node);
|
list_del(&curr->node);
|
||||||
dma_fence_put(&curr->f);
|
dma_fence_put(&curr->f);
|
||||||
}
|
}
|
||||||
|
|
||||||
dma_fence_signal_locked(&signaled->f);
|
dma_fence_signal_locked(&signaled->f);
|
||||||
|
if (signaled->e) {
|
||||||
|
drm_send_event(vgdev->ddev, &signaled->e->base);
|
||||||
|
signaled->e = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
list_del(&signaled->node);
|
list_del(&signaled->node);
|
||||||
dma_fence_put(&signaled->f);
|
dma_fence_put(&signaled->f);
|
||||||
break;
|
break;
|
||||||
|
@ -38,6 +38,36 @@
|
|||||||
VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
|
VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
|
||||||
VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
|
VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
|
||||||
|
|
||||||
|
static int virtio_gpu_fence_event_create(struct drm_device *dev,
|
||||||
|
struct drm_file *file,
|
||||||
|
struct virtio_gpu_fence *fence,
|
||||||
|
uint32_t ring_idx)
|
||||||
|
{
|
||||||
|
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
|
||||||
|
struct virtio_gpu_fence_event *e = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!(vfpriv->ring_idx_mask & (1 << ring_idx)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
e = kzalloc(sizeof(*e), GFP_KERNEL);
|
||||||
|
if (!e)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED_INTERNAL;
|
||||||
|
e->event.length = sizeof(e->event);
|
||||||
|
|
||||||
|
ret = drm_event_reserve_init(dev, file, &e->base, &e->event);
|
||||||
|
if (ret)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
fence->e = e;
|
||||||
|
return 0;
|
||||||
|
free:
|
||||||
|
kfree(e);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
|
/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
|
||||||
static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
|
static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
|
||||||
struct virtio_gpu_fpriv *vfpriv)
|
struct virtio_gpu_fpriv *vfpriv)
|
||||||
@ -195,6 +225,10 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
|
|||||||
goto out_unresv;
|
goto out_unresv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx);
|
||||||
|
if (ret)
|
||||||
|
goto out_unresv;
|
||||||
|
|
||||||
if (out_fence_fd >= 0) {
|
if (out_fence_fd >= 0) {
|
||||||
sync_file = sync_file_create(&out_fence->f);
|
sync_file = sync_file_create(&out_fence->f);
|
||||||
if (!sync_file) {
|
if (!sync_file) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user