Message ID | 20210917010842.503-12-gurchetansingh@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Context types | expand |
Hi Gurchetan, > > 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. [Kasireddy, Vivek] Given my limited understanding of virtio_gpu 3D/Virgl, I am wondering why you'd need a new internal event associated with a fence; would you not be able to accomplish the same by adding the out_fence_fd (from execbuf) to your userspace's event loop (in addition to DRM fd) and get signalled? Thanks, Vivek > > Signed-off-by: Gurchetan Singh <gurchetansingh@chromium.org> > Acked-by: Nicholas Verne <nverne@chromium.org> > --- > drivers/gpu/drm/virtio/virtgpu_drv.c | 43 +++++++++++++++++++++++++- > drivers/gpu/drm/virtio/virtgpu_drv.h | 7 +++++ > drivers/gpu/drm/virtio/virtgpu_fence.c | 10 ++++++ > drivers/gpu/drm/virtio/virtgpu_ioctl.c | 34 ++++++++++++++++++++ > 4 files changed, 93 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c > index 9d963f1fda8f..749db18dcfa2 100644 > --- a/drivers/gpu/drm/virtio/virtgpu_drv.c > +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c > @@ -29,6 +29,8 @@ > #include <linux/module.h> > #include <linux/console.h> > #include <linux/pci.h> > +#include <linux/poll.h> > +#include <linux/wait.h> > > #include <drm/drm.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); > } > > +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[] = { > { VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID }, > { 0 }, > @@ -194,7 +225,17 @@ MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>"); > MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>"); > 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 = { > .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | > DRIVER_ATOMIC, > diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h > index cb60d52c2bd1..e0265fe74aa5 100644 > --- a/drivers/gpu/drm/virtio/virtgpu_drv.h > +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h > @@ -138,11 +138,18 @@ struct virtio_gpu_fence_driver { > 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 dma_fence f; > uint32_t ring_idx; > uint64_t fence_id; > bool emit_fence_info; > + struct virtio_gpu_fence_event *e; > struct virtio_gpu_fence_driver *drv; > struct list_head node; > }; > diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c > b/drivers/gpu/drm/virtio/virtgpu_fence.c > index 98a00c1e654d..f28357dbde35 100644 > --- a/drivers/gpu/drm/virtio/virtgpu_fence.c > +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c > @@ -152,11 +152,21 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device > *vgdev, > continue; > > dma_fence_signal_locked(&curr->f); > + if (curr->e) { > + drm_send_event(vgdev->ddev, &curr->e->base); > + curr->e = NULL; > + } > + > list_del(&curr->node); > dma_fence_put(&curr->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); > dma_fence_put(&signaled->f); > break; > diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c > index be7b22a03884..fdaa7f3d9eeb 100644 > --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c > +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c > @@ -38,6 +38,36 @@ > VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \ > 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. */ > static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev, > struct virtio_gpu_fpriv *vfpriv) > @@ -195,6 +225,10 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, > void *data, > 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) { > sync_file = sync_file_create(&out_fence->f); > if (!sync_file) { > -- > 2.33.0.464.g1972c5931b-goog
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 9d963f1fda8f..749db18dcfa2 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -29,6 +29,8 @@ #include <linux/module.h> #include <linux/console.h> #include <linux/pci.h> +#include <linux/poll.h> +#include <linux/wait.h> #include <drm/drm.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); } +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[] = { { VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID }, { 0 }, @@ -194,7 +225,17 @@ MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>"); MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>"); 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 = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index cb60d52c2bd1..e0265fe74aa5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -138,11 +138,18 @@ struct virtio_gpu_fence_driver { 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 dma_fence f; uint32_t ring_idx; uint64_t fence_id; bool emit_fence_info; + struct virtio_gpu_fence_event *e; struct virtio_gpu_fence_driver *drv; struct list_head node; }; diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c index 98a00c1e654d..f28357dbde35 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fence.c +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c @@ -152,11 +152,21 @@ void virtio_gpu_fence_event_process(struct virtio_gpu_device *vgdev, continue; dma_fence_signal_locked(&curr->f); + if (curr->e) { + drm_send_event(vgdev->ddev, &curr->e->base); + curr->e = NULL; + } + list_del(&curr->node); dma_fence_put(&curr->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); dma_fence_put(&signaled->f); break; diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index be7b22a03884..fdaa7f3d9eeb 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -38,6 +38,36 @@ VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \ 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. */ static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev, struct virtio_gpu_fpriv *vfpriv) @@ -195,6 +225,10 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, 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) { sync_file = sync_file_create(&out_fence->f); if (!sync_file) {