@@ -82,6 +82,39 @@ static irqreturn_t vhost_vdpa_config_cb(void *private)
82
82
return IRQ_HANDLED ;
83
83
}
84
84
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
+
85
118
static void vhost_vdpa_reset (struct vhost_vdpa * v )
86
119
{
87
120
struct vdpa_device * vdpa = v -> vdpa ;
@@ -121,11 +154,15 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp)
121
154
{
122
155
struct vdpa_device * vdpa = v -> vdpa ;
123
156
const struct vdpa_config_ops * ops = vdpa -> config ;
124
- u8 status ;
157
+ u8 status , status_old ;
158
+ int nvqs = v -> nvqs ;
159
+ u16 i ;
125
160
126
161
if (copy_from_user (& status , statusp , sizeof (status )))
127
162
return - EFAULT ;
128
163
164
+ status_old = ops -> get_status (vdpa );
165
+
129
166
/*
130
167
* Userspace shouldn't remove status bits unless reset the
131
168
* status to 0.
@@ -135,6 +172,15 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp)
135
172
136
173
ops -> set_status (vdpa , status );
137
174
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
+
138
184
return 0 ;
139
185
}
140
186
@@ -293,6 +339,7 @@ static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp)
293
339
294
340
return 0 ;
295
341
}
342
+
296
343
static long vhost_vdpa_vring_ioctl (struct vhost_vdpa * v , unsigned int cmd ,
297
344
void __user * argp )
298
345
{
@@ -351,6 +398,7 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
351
398
cb .private = NULL ;
352
399
}
353
400
ops -> set_vq_cb (vdpa , idx , & cb );
401
+ vhost_vdpa_setup_vq_irq (v , idx );
354
402
break ;
355
403
356
404
case VHOST_SET_VRING_NUM :
@@ -726,6 +774,18 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
726
774
return r ;
727
775
}
728
776
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
+
729
789
static int vhost_vdpa_release (struct inode * inode , struct file * filep )
730
790
{
731
791
struct vhost_vdpa * v = filep -> private_data ;
@@ -738,6 +798,7 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
738
798
vhost_vdpa_iotlb_free (v );
739
799
vhost_vdpa_free_domain (v );
740
800
vhost_vdpa_config_put (v );
801
+ vhost_vdpa_clean_irq (v );
741
802
vhost_dev_cleanup (& v -> vdev );
742
803
kfree (v -> vdev .vqs );
743
804
mutex_unlock (& d -> mutex );
0 commit comments