@@ -53,6 +53,7 @@ struct virtio_uml_device {
53
53
struct virtio_device vdev ;
54
54
struct platform_device * pdev ;
55
55
56
+ spinlock_t sock_lock ;
56
57
int sock , req_fd ;
57
58
u64 features ;
58
59
u64 protocol_features ;
@@ -189,6 +190,7 @@ static int vhost_user_send(struct virtio_uml_device *vu_dev,
189
190
int * fds , size_t num_fds )
190
191
{
191
192
size_t size = sizeof (msg -> header ) + msg -> header .size ;
193
+ unsigned long flags ;
192
194
bool request_ack ;
193
195
int rc ;
194
196
@@ -207,24 +209,28 @@ static int vhost_user_send(struct virtio_uml_device *vu_dev,
207
209
if (request_ack )
208
210
msg -> header .flags |= VHOST_USER_FLAG_NEED_REPLY ;
209
211
212
+ spin_lock_irqsave (& vu_dev -> sock_lock , flags );
210
213
rc = full_sendmsg_fds (vu_dev -> sock , msg , size , fds , num_fds );
211
214
if (rc < 0 )
212
- return rc ;
215
+ goto out ;
213
216
214
217
if (request_ack ) {
215
218
uint64_t status ;
216
219
217
220
rc = vhost_user_recv_u64 (vu_dev , & status );
218
221
if (rc )
219
- return rc ;
222
+ goto out ;
220
223
221
224
if (status ) {
222
225
vu_err (vu_dev , "slave reports error: %llu\n" , status );
223
- return - EIO ;
226
+ rc = - EIO ;
227
+ goto out ;
224
228
}
225
229
}
226
230
227
- return 0 ;
231
+ out :
232
+ spin_unlock_irqrestore (& vu_dev -> sock_lock , flags );
233
+ return rc ;
228
234
}
229
235
230
236
static int vhost_user_send_no_payload (struct virtio_uml_device * vu_dev ,
@@ -324,6 +330,7 @@ static void vhost_user_reply(struct virtio_uml_device *vu_dev,
324
330
static irqreturn_t vu_req_interrupt (int irq , void * data )
325
331
{
326
332
struct virtio_uml_device * vu_dev = data ;
333
+ struct virtqueue * vq ;
327
334
int response = 1 ;
328
335
struct {
329
336
struct vhost_user_msg msg ;
@@ -343,6 +350,15 @@ static irqreturn_t vu_req_interrupt(int irq, void *data)
343
350
virtio_config_changed (& vu_dev -> vdev );
344
351
response = 0 ;
345
352
break ;
353
+ case VHOST_USER_SLAVE_VRING_CALL :
354
+ virtio_device_for_each_vq ((& vu_dev -> vdev ), vq ) {
355
+ if (vq -> index == msg .msg .payload .vring_state .index ) {
356
+ response = 0 ;
357
+ vring_interrupt (0 /* ignored */ , vq );
358
+ break ;
359
+ }
360
+ }
361
+ break ;
346
362
case VHOST_USER_SLAVE_IOTLB_MSG :
347
363
/* not supported - VIRTIO_F_IOMMU_PLATFORM */
348
364
case VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG :
@@ -684,6 +700,15 @@ static bool vu_notify(struct virtqueue *vq)
684
700
const uint64_t n = 1 ;
685
701
int rc ;
686
702
703
+ if (info -> kick_fd < 0 ) {
704
+ struct virtio_uml_device * vu_dev ;
705
+
706
+ vu_dev = to_virtio_uml_device (vq -> vdev );
707
+
708
+ return vhost_user_set_vring_state (vu_dev , VHOST_USER_VRING_KICK ,
709
+ vq -> index , 0 ) == 0 ;
710
+ }
711
+
687
712
do {
688
713
rc = os_write_file (info -> kick_fd , & n , sizeof (n ));
689
714
} while (rc == - EINTR );
@@ -749,10 +774,13 @@ static void vu_del_vq(struct virtqueue *vq)
749
774
{
750
775
struct virtio_uml_vq_info * info = vq -> priv ;
751
776
752
- um_free_irq (VIRTIO_IRQ , vq );
777
+ if (info -> call_fd >= 0 ) {
778
+ um_free_irq (VIRTIO_IRQ , vq );
779
+ os_close_file (info -> call_fd );
780
+ }
753
781
754
- os_close_file (info -> call_fd );
755
- os_close_file (info -> kick_fd );
782
+ if (info -> kick_fd >= 0 )
783
+ os_close_file (info -> kick_fd );
756
784
757
785
vring_del_virtqueue (vq );
758
786
kfree (info );
@@ -782,6 +810,15 @@ static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
782
810
int call_fds [2 ];
783
811
int rc ;
784
812
813
+ /* no call FD needed/desired in this case */
814
+ if (vu_dev -> protocol_features &
815
+ BIT_ULL (VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS ) &&
816
+ vu_dev -> protocol_features &
817
+ BIT_ULL (VHOST_USER_PROTOCOL_F_SLAVE_REQ )) {
818
+ info -> call_fd = -1 ;
819
+ return 0 ;
820
+ }
821
+
785
822
/* Use a pipe for call fd, since SIGIO is not supported for eventfd */
786
823
rc = os_pipe (call_fds , true, true);
787
824
if (rc < 0 )
@@ -838,10 +875,15 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
838
875
vq -> priv = info ;
839
876
num = virtqueue_get_vring_size (vq );
840
877
841
- rc = os_eventfd (0 , 0 );
842
- if (rc < 0 )
843
- goto error_kick ;
844
- info -> kick_fd = rc ;
878
+ if (vu_dev -> protocol_features &
879
+ BIT_ULL (VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS )) {
880
+ info -> kick_fd = -1 ;
881
+ } else {
882
+ rc = os_eventfd (0 , 0 );
883
+ if (rc < 0 )
884
+ goto error_kick ;
885
+ info -> kick_fd = rc ;
886
+ }
845
887
846
888
rc = vu_setup_vq_call_fd (vu_dev , vq );
847
889
if (rc )
@@ -866,10 +908,13 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
866
908
return vq ;
867
909
868
910
error_setup :
869
- um_free_irq (VIRTIO_IRQ , vq );
870
- os_close_file (info -> call_fd );
911
+ if (info -> call_fd >= 0 ) {
912
+ um_free_irq (VIRTIO_IRQ , vq );
913
+ os_close_file (info -> call_fd );
914
+ }
871
915
error_call :
872
- os_close_file (info -> kick_fd );
916
+ if (info -> kick_fd >= 0 )
917
+ os_close_file (info -> kick_fd );
873
918
error_kick :
874
919
vring_del_virtqueue (vq );
875
920
error_create :
@@ -908,10 +953,12 @@ static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
908
953
list_for_each_entry (vq , & vdev -> vqs , list ) {
909
954
struct virtio_uml_vq_info * info = vq -> priv ;
910
955
911
- rc = vhost_user_set_vring_kick (vu_dev , vq -> index ,
912
- info -> kick_fd );
913
- if (rc )
914
- goto error_setup ;
956
+ if (info -> kick_fd >= 0 ) {
957
+ rc = vhost_user_set_vring_kick (vu_dev , vq -> index ,
958
+ info -> kick_fd );
959
+ if (rc )
960
+ goto error_setup ;
961
+ }
915
962
916
963
rc = vhost_user_set_vring_enable (vu_dev , vq -> index , true);
917
964
if (rc )
@@ -1008,6 +1055,8 @@ static int virtio_uml_probe(struct platform_device *pdev)
1008
1055
return rc ;
1009
1056
vu_dev -> sock = rc ;
1010
1057
1058
+ spin_lock_init (& vu_dev -> sock_lock );
1059
+
1011
1060
rc = vhost_user_init (vu_dev );
1012
1061
if (rc )
1013
1062
goto error_init ;
0 commit comments