Jason Wang
2021-Mar-04 06:59 UTC
[RFC v4 10/11] vduse: Introduce a workqueue for irq injection
On 2021/2/23 7:50 ??, Xie Yongji wrote:> This patch introduces a workqueue to support injecting > virtqueue's interrupt asynchronously. This is mainly > for performance considerations which makes sure the push() > and pop() for used vring can be asynchronous.Do you have pref numbers for this patch? Thanks> > Signed-off-by: Xie Yongji <xieyongji at bytedance.com> > --- > drivers/vdpa/vdpa_user/vduse_dev.c | 29 +++++++++++++++++++++++------ > 1 file changed, 23 insertions(+), 6 deletions(-) > > diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c > index 8042d3fa57f1..f5adeb9ee027 100644 > --- a/drivers/vdpa/vdpa_user/vduse_dev.c > +++ b/drivers/vdpa/vdpa_user/vduse_dev.c > @@ -42,6 +42,7 @@ struct vduse_virtqueue { > spinlock_t irq_lock; > struct eventfd_ctx *kickfd; > struct vdpa_callback cb; > + struct work_struct inject; > }; > > struct vduse_dev; > @@ -99,6 +100,7 @@ static DEFINE_IDA(vduse_ida); > > static dev_t vduse_major; > static struct class *vduse_class; > +static struct workqueue_struct *vduse_irq_wq; > > static inline struct vduse_dev *vdpa_to_vduse(struct vdpa_device *vdpa) > { > @@ -852,6 +854,17 @@ static int vduse_kickfd_setup(struct vduse_dev *dev, > return 0; > } > > +static void vduse_vq_irq_inject(struct work_struct *work) > +{ > + struct vduse_virtqueue *vq = container_of(work, > + struct vduse_virtqueue, inject); > + > + spin_lock_irq(&vq->irq_lock); > + if (vq->ready && vq->cb.callback) > + vq->cb.callback(vq->cb.private); > + spin_unlock_irq(&vq->irq_lock); > +} > + > static long vduse_dev_ioctl(struct file *file, unsigned int cmd, > unsigned long arg) > { > @@ -917,12 +930,7 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, > break; > > vq = &dev->vqs[arg]; > - spin_lock_irq(&vq->irq_lock); > - if (vq->ready && vq->cb.callback) { > - vq->cb.callback(vq->cb.private); > - ret = 0; > - } > - spin_unlock_irq(&vq->irq_lock); > + queue_work(vduse_irq_wq, &vq->inject); > break; > } > case VDUSE_INJECT_CONFIG_IRQ: > @@ -1109,6 +1117,7 @@ static int vduse_create_dev(struct vduse_dev_config *config) > > for (i = 0; i < dev->vq_num; i++) { > dev->vqs[i].index = i; > + INIT_WORK(&dev->vqs[i].inject, vduse_vq_irq_inject); > spin_lock_init(&dev->vqs[i].kick_lock); > spin_lock_init(&dev->vqs[i].irq_lock); > } > @@ -1333,6 +1342,11 @@ static int vduse_init(void) > if (ret) > goto err_chardev; > > + vduse_irq_wq = alloc_workqueue("vduse-irq", > + WQ_HIGHPRI | WQ_SYSFS | WQ_UNBOUND, 0); > + if (!vduse_irq_wq) > + goto err_wq; > + > ret = vduse_domain_init(); > if (ret) > goto err_domain; > @@ -1344,6 +1358,8 @@ static int vduse_init(void) > return 0; > err_mgmtdev: > vduse_domain_exit(); > +err_wq: > + destroy_workqueue(vduse_irq_wq); > err_domain: > unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); > err_chardev: > @@ -1359,6 +1375,7 @@ static void vduse_exit(void) > misc_deregister(&vduse_misc); > class_destroy(vduse_class); > unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); > + destroy_workqueue(vduse_irq_wq); > vduse_domain_exit(); > vduse_mgmtdev_exit(); > }