Skip to content

Commit 2cf1ba9

Browse files
Zhu Lingshanmstsirkin
authored andcommitted
vhost_vdpa: implement IRQ offloading in vhost_vdpa
This patch introduce a set of functions for setup/unsetup and update irq offloading respectively by register/unregister and re-register the irq_bypass_producer. With these functions, this commit can setup/unsetup irq offloading through setting DRIVER_OK/!DRIVER_OK, and update irq offloading through SET_VRING_CALL. Signed-off-by: Zhu Lingshan <[email protected]> Suggested-by: Jason Wang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 7164675 commit 2cf1ba9

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

drivers/vhost/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ config VHOST_VDPA
6565
tristate "Vhost driver for vDPA-based backend"
6666
depends on EVENTFD
6767
select VHOST
68+
select IRQ_BYPASS_MANAGER
6869
depends on VDPA
6970
help
7071
This kernel module can be loaded in host kernel to accelerate

drivers/vhost/vdpa.c

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,39 @@ static irqreturn_t vhost_vdpa_config_cb(void *private)
8282
return IRQ_HANDLED;
8383
}
8484

85+
static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid)
86+
{
87+
struct vhost_virtqueue *vq = &v->vqs[qid];
88+
const struct vdpa_config_ops *ops = v->vdpa->config;
89+
struct vdpa_device *vdpa = v->vdpa;
90+
int ret, irq;
91+
92+
if (!ops->get_vq_irq)
93+
return;
94+
95+
irq = ops->get_vq_irq(vdpa, qid);
96+
spin_lock(&vq->call_ctx.ctx_lock);
97+
irq_bypass_unregister_producer(&vq->call_ctx.producer);
98+
if (!vq->call_ctx.ctx || irq < 0) {
99+
spin_unlock(&vq->call_ctx.ctx_lock);
100+
return;
101+
}
102+
103+
vq->call_ctx.producer.token = vq->call_ctx.ctx;
104+
vq->call_ctx.producer.irq = irq;
105+
ret = irq_bypass_register_producer(&vq->call_ctx.producer);
106+
spin_unlock(&vq->call_ctx.ctx_lock);
107+
}
108+
109+
static void vhost_vdpa_unsetup_vq_irq(struct vhost_vdpa *v, u16 qid)
110+
{
111+
struct vhost_virtqueue *vq = &v->vqs[qid];
112+
113+
spin_lock(&vq->call_ctx.ctx_lock);
114+
irq_bypass_unregister_producer(&vq->call_ctx.producer);
115+
spin_unlock(&vq->call_ctx.ctx_lock);
116+
}
117+
85118
static void vhost_vdpa_reset(struct vhost_vdpa *v)
86119
{
87120
struct vdpa_device *vdpa = v->vdpa;
@@ -121,11 +154,15 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp)
121154
{
122155
struct vdpa_device *vdpa = v->vdpa;
123156
const struct vdpa_config_ops *ops = vdpa->config;
124-
u8 status;
157+
u8 status, status_old;
158+
int nvqs = v->nvqs;
159+
u16 i;
125160

126161
if (copy_from_user(&status, statusp, sizeof(status)))
127162
return -EFAULT;
128163

164+
status_old = ops->get_status(vdpa);
165+
129166
/*
130167
* Userspace shouldn't remove status bits unless reset the
131168
* status to 0.
@@ -135,6 +172,15 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp)
135172

136173
ops->set_status(vdpa, status);
137174

175+
/* vq irq is not expected to be changed once DRIVER_OK is set */
176+
if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && !(status_old & VIRTIO_CONFIG_S_DRIVER_OK))
177+
for (i = 0; i < nvqs; i++)
178+
vhost_vdpa_setup_vq_irq(v, i);
179+
180+
if ((status_old & VIRTIO_CONFIG_S_DRIVER_OK) && !(status & VIRTIO_CONFIG_S_DRIVER_OK))
181+
for (i = 0; i < nvqs; i++)
182+
vhost_vdpa_unsetup_vq_irq(v, i);
183+
138184
return 0;
139185
}
140186

@@ -293,6 +339,7 @@ static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp)
293339

294340
return 0;
295341
}
342+
296343
static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
297344
void __user *argp)
298345
{
@@ -351,6 +398,7 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
351398
cb.private = NULL;
352399
}
353400
ops->set_vq_cb(vdpa, idx, &cb);
401+
vhost_vdpa_setup_vq_irq(v, idx);
354402
break;
355403

356404
case VHOST_SET_VRING_NUM:
@@ -726,6 +774,18 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
726774
return r;
727775
}
728776

777+
static void vhost_vdpa_clean_irq(struct vhost_vdpa *v)
778+
{
779+
struct vhost_virtqueue *vq;
780+
int i;
781+
782+
for (i = 0; i < v->nvqs; i++) {
783+
vq = &v->vqs[i];
784+
if (vq->call_ctx.producer.irq)
785+
irq_bypass_unregister_producer(&vq->call_ctx.producer);
786+
}
787+
}
788+
729789
static int vhost_vdpa_release(struct inode *inode, struct file *filep)
730790
{
731791
struct vhost_vdpa *v = filep->private_data;
@@ -738,6 +798,7 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
738798
vhost_vdpa_iotlb_free(v);
739799
vhost_vdpa_free_domain(v);
740800
vhost_vdpa_config_put(v);
801+
vhost_vdpa_clean_irq(v);
741802
vhost_dev_cleanup(&v->vdev);
742803
kfree(v->vdev.vqs);
743804
mutex_unlock(&d->mutex);

0 commit comments

Comments
 (0)