@@ -38,6 +38,132 @@ static bool vp_is_avq(struct virtio_device *vdev, unsigned int index)
3838 return index == vp_dev -> admin_vq .vq_index ;
3939}
4040
41+ static int virtqueue_exec_admin_cmd (struct virtio_pci_admin_vq * admin_vq ,
42+ struct scatterlist * * sgs ,
43+ unsigned int out_num ,
44+ unsigned int in_num ,
45+ void * data )
46+ {
47+ struct virtqueue * vq ;
48+ int ret , len ;
49+
50+ vq = admin_vq -> info .vq ;
51+ if (!vq )
52+ return - EIO ;
53+
54+ ret = virtqueue_add_sgs (vq , sgs , out_num , in_num , data , GFP_KERNEL );
55+ if (ret < 0 )
56+ return - EIO ;
57+
58+ if (unlikely (!virtqueue_kick (vq )))
59+ return - EIO ;
60+
61+ while (!virtqueue_get_buf (vq , & len ) &&
62+ !virtqueue_is_broken (vq ))
63+ cpu_relax ();
64+
65+ if (virtqueue_is_broken (vq ))
66+ return - EIO ;
67+
68+ return 0 ;
69+ }
70+
71+ int vp_modern_admin_cmd_exec (struct virtio_device * vdev ,
72+ struct virtio_admin_cmd * cmd )
73+ {
74+ struct scatterlist * sgs [VIRTIO_AVQ_SGS_MAX ], hdr , stat ;
75+ struct virtio_pci_device * vp_dev = to_vp_device (vdev );
76+ struct virtio_admin_cmd_status * va_status ;
77+ unsigned int out_num = 0 , in_num = 0 ;
78+ struct virtio_admin_cmd_hdr * va_hdr ;
79+ u16 status ;
80+ int ret ;
81+
82+ if (!virtio_has_feature (vdev , VIRTIO_F_ADMIN_VQ ))
83+ return - EOPNOTSUPP ;
84+
85+ va_status = kzalloc (sizeof (* va_status ), GFP_KERNEL );
86+ if (!va_status )
87+ return - ENOMEM ;
88+
89+ va_hdr = kzalloc (sizeof (* va_hdr ), GFP_KERNEL );
90+ if (!va_hdr ) {
91+ ret = - ENOMEM ;
92+ goto err_alloc ;
93+ }
94+
95+ va_hdr -> opcode = cmd -> opcode ;
96+ va_hdr -> group_type = cmd -> group_type ;
97+ va_hdr -> group_member_id = cmd -> group_member_id ;
98+
99+ /* Add header */
100+ sg_init_one (& hdr , va_hdr , sizeof (* va_hdr ));
101+ sgs [out_num ] = & hdr ;
102+ out_num ++ ;
103+
104+ if (cmd -> data_sg ) {
105+ sgs [out_num ] = cmd -> data_sg ;
106+ out_num ++ ;
107+ }
108+
109+ /* Add return status */
110+ sg_init_one (& stat , va_status , sizeof (* va_status ));
111+ sgs [out_num + in_num ] = & stat ;
112+ in_num ++ ;
113+
114+ if (cmd -> result_sg ) {
115+ sgs [out_num + in_num ] = cmd -> result_sg ;
116+ in_num ++ ;
117+ }
118+
119+ mutex_lock (& vp_dev -> admin_vq .cmd_lock );
120+ ret = virtqueue_exec_admin_cmd (& vp_dev -> admin_vq , sgs ,
121+ out_num , in_num , sgs );
122+ mutex_unlock (& vp_dev -> admin_vq .cmd_lock );
123+
124+ if (ret ) {
125+ dev_err (& vdev -> dev ,
126+ "Failed to execute command on admin vq: %d\n." , ret );
127+ goto err_cmd_exec ;
128+ }
129+
130+ status = le16_to_cpu (va_status -> status );
131+ if (status != VIRTIO_ADMIN_STATUS_OK ) {
132+ dev_err (& vdev -> dev ,
133+ "admin command error: status(%#x) qualifier(%#x)\n" ,
134+ status , le16_to_cpu (va_status -> status_qualifier ));
135+ ret = - status ;
136+ }
137+
138+ err_cmd_exec :
139+ kfree (va_hdr );
140+ err_alloc :
141+ kfree (va_status );
142+ return ret ;
143+ }
144+
145+ static void vp_modern_avq_activate (struct virtio_device * vdev )
146+ {
147+ struct virtio_pci_device * vp_dev = to_vp_device (vdev );
148+ struct virtio_pci_admin_vq * admin_vq = & vp_dev -> admin_vq ;
149+
150+ if (!virtio_has_feature (vdev , VIRTIO_F_ADMIN_VQ ))
151+ return ;
152+
153+ __virtqueue_unbreak (admin_vq -> info .vq );
154+ }
155+
156+ static void vp_modern_avq_deactivate (struct virtio_device * vdev )
157+ {
158+ struct virtio_pci_device * vp_dev = to_vp_device (vdev );
159+ struct virtio_pci_admin_vq * admin_vq = & vp_dev -> admin_vq ;
160+
161+ if (!virtio_has_feature (vdev , VIRTIO_F_ADMIN_VQ ))
162+ return ;
163+
164+ __virtqueue_break (admin_vq -> info .vq );
165+ }
166+
41167static void vp_transport_features (struct virtio_device * vdev , u64 features )
42168{
43169 struct virtio_pci_device * vp_dev = to_vp_device (vdev );
@@ -213,6 +339,8 @@ static void vp_set_status(struct virtio_device *vdev, u8 status)
213339 /* We should never be setting status to 0. */
214340 BUG_ON (status == 0 );
215341 vp_modern_set_status (& vp_dev -> mdev , status );
342+ if (status & VIRTIO_CONFIG_S_DRIVER_OK )
343+ vp_modern_avq_activate (vdev );
216344}
217345
218346static void vp_reset (struct virtio_device * vdev )
@@ -229,6 +357,9 @@ static void vp_reset(struct virtio_device *vdev)
229357 */
230358 while (vp_modern_get_status (mdev ))
231359 msleep (1 );
360+
361+ vp_modern_avq_deactivate (vdev );
362+
232363 /* Flush pending VQ/configuration callbacks. */
233364 vp_synchronize_vectors (vdev );
234365}
@@ -404,8 +535,11 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
404535 goto err ;
405536 }
406537
407- if (is_avq )
538+ if (is_avq ) {
539+ mutex_lock (& vp_dev -> admin_vq .cmd_lock );
408540 vp_dev -> admin_vq .info .vq = vq ;
541+ mutex_unlock (& vp_dev -> admin_vq .cmd_lock );
542+ }
409543
410544 return vq ;
411545
@@ -442,8 +576,11 @@ static void del_vq(struct virtio_pci_vq_info *info)
442576 struct virtio_pci_device * vp_dev = to_vp_device (vq -> vdev );
443577 struct virtio_pci_modern_device * mdev = & vp_dev -> mdev ;
444578
445- if (vp_is_avq (& vp_dev -> vdev , vq -> index ))
579+ if (vp_is_avq (& vp_dev -> vdev , vq -> index )) {
580+ mutex_lock (& vp_dev -> admin_vq .cmd_lock );
446581 vp_dev -> admin_vq .info .vq = NULL ;
582+ mutex_unlock (& vp_dev -> admin_vq .cmd_lock );
583+ }
447584
448585 if (vp_dev -> msix_enabled )
449586 vp_modern_queue_vector (mdev , vq -> index ,
@@ -662,12 +799,14 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev)
662799 vp_dev -> isr = mdev -> isr ;
663800 vp_dev -> vdev .id = mdev -> id ;
664801
802+ mutex_init (& vp_dev -> admin_vq .cmd_lock );
665803 return 0 ;
666804}
667805
668806void virtio_pci_modern_remove (struct virtio_pci_device * vp_dev )
669807{
670808 struct virtio_pci_modern_device * mdev = & vp_dev -> mdev ;
671809
810+ mutex_destroy (& vp_dev -> admin_vq .cmd_lock );
672811 vp_modern_remove (mdev );
673812}
0 commit comments