1919#define VIRTIO_RING_NO_LEGACY
2020#include "virtio_pci_common.h"
2121
22+ #define VIRTIO_AVQ_SGS_MAX 4
23+
2224static u64 vp_get_features (struct virtio_device * vdev )
2325{
2426 struct virtio_pci_device * vp_dev = to_vp_device (vdev );
2527
2628 return vp_modern_get_features (& vp_dev -> mdev );
2729}
2830
31+ static bool vp_is_avq (struct virtio_device * vdev , unsigned int index )
32+ {
33+ struct virtio_pci_device * vp_dev = to_vp_device (vdev );
34+
35+ if (!virtio_has_feature (vdev , VIRTIO_F_ADMIN_VQ ))
36+ return false;
37+
38+ return index == vp_dev -> admin_vq .vq_index ;
39+ }
40+
2941static void vp_transport_features (struct virtio_device * vdev , u64 features )
3042{
3143 struct virtio_pci_device * vp_dev = to_vp_device (vdev );
@@ -37,6 +49,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
3749
3850 if (features & BIT_ULL (VIRTIO_F_RING_RESET ))
3951 __virtio_set_bit (vdev , VIRTIO_F_RING_RESET );
52+
53+ if (features & BIT_ULL (VIRTIO_F_ADMIN_VQ ))
54+ __virtio_set_bit (vdev , VIRTIO_F_ADMIN_VQ );
4055}
4156
4257static int __vp_check_common_size_one_feature (struct virtio_device * vdev , u32 fbit ,
@@ -69,6 +84,9 @@ static int vp_check_common_size(struct virtio_device *vdev)
6984 if (vp_check_common_size_one_feature (vdev , VIRTIO_F_RING_RESET , queue_reset ))
7085 return - EINVAL ;
7186
87+ if (vp_check_common_size_one_feature (vdev , VIRTIO_F_ADMIN_VQ , admin_queue_num ))
88+ return - EINVAL ;
89+
7290 return 0 ;
7391}
7492
@@ -345,6 +363,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
345363 struct virtio_pci_modern_device * mdev = & vp_dev -> mdev ;
346364 bool (* notify )(struct virtqueue * vq );
347365 struct virtqueue * vq ;
366+ bool is_avq ;
348367 u16 num ;
349368 int err ;
350369
@@ -353,11 +372,13 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
353372 else
354373 notify = vp_notify ;
355374
356- if (index >= vp_modern_get_num_queues (mdev ))
375+ is_avq = vp_is_avq (& vp_dev -> vdev , index );
376+ if (index >= vp_modern_get_num_queues (mdev ) && !is_avq )
357377 return ERR_PTR (- EINVAL );
358378
379+ num = is_avq ?
380+ VIRTIO_AVQ_SGS_MAX : vp_modern_get_queue_size (mdev , index );
359381 /* Check if queue is either not available or already active. */
360- num = vp_modern_get_queue_size (mdev , index );
361382 if (!num || vp_modern_get_queue_enable (mdev , index ))
362383 return ERR_PTR (- ENOENT );
363384
@@ -383,6 +404,9 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
383404 goto err ;
384405 }
385406
407+ if (is_avq )
408+ vp_dev -> admin_vq .info .vq = vq ;
409+
386410 return vq ;
387411
388412err :
@@ -418,6 +442,9 @@ static void del_vq(struct virtio_pci_vq_info *info)
418442 struct virtio_pci_device * vp_dev = to_vp_device (vq -> vdev );
419443 struct virtio_pci_modern_device * mdev = & vp_dev -> mdev ;
420444
445+ if (vp_is_avq (& vp_dev -> vdev , vq -> index ))
446+ vp_dev -> admin_vq .info .vq = NULL ;
447+
421448 if (vp_dev -> msix_enabled )
422449 vp_modern_queue_vector (mdev , vq -> index ,
423450 VIRTIO_MSI_NO_VECTOR );
@@ -527,6 +554,45 @@ static bool vp_get_shm_region(struct virtio_device *vdev,
527554 return true;
528555}
529556
557+ static int vp_modern_create_avq (struct virtio_device * vdev )
558+ {
559+ struct virtio_pci_device * vp_dev = to_vp_device (vdev );
560+ struct virtio_pci_admin_vq * avq ;
561+ struct virtqueue * vq ;
562+ u16 admin_q_num ;
563+
564+ if (!virtio_has_feature (vdev , VIRTIO_F_ADMIN_VQ ))
565+ return 0 ;
566+
567+ admin_q_num = vp_modern_avq_num (& vp_dev -> mdev );
568+ if (!admin_q_num )
569+ return - EINVAL ;
570+
571+ avq = & vp_dev -> admin_vq ;
572+ avq -> vq_index = vp_modern_avq_index (& vp_dev -> mdev );
573+ sprintf (avq -> name , "avq.%u" , avq -> vq_index );
574+ vq = vp_dev -> setup_vq (vp_dev , & vp_dev -> admin_vq .info , avq -> vq_index , NULL ,
575+ avq -> name , NULL , VIRTIO_MSI_NO_VECTOR );
576+ if (IS_ERR (vq )) {
577+ dev_err (& vdev -> dev , "failed to setup admin virtqueue, err=%ld" ,
578+ PTR_ERR (vq ));
579+ return PTR_ERR (vq );
580+ }
581+
582+ vp_modern_set_queue_enable (& vp_dev -> mdev , avq -> info .vq -> index , true);
583+ return 0 ;
584+ }
585+
586+ static void vp_modern_destroy_avq (struct virtio_device * vdev )
587+ {
588+ struct virtio_pci_device * vp_dev = to_vp_device (vdev );
589+
590+ if (!virtio_has_feature (vdev , VIRTIO_F_ADMIN_VQ ))
591+ return ;
592+
593+ vp_dev -> del_vq (& vp_dev -> admin_vq .info );
594+ }
595+
530596static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
531597 .get = NULL ,
532598 .set = NULL ,
@@ -545,6 +611,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
545611 .get_shm_region = vp_get_shm_region ,
546612 .disable_vq_and_reset = vp_modern_disable_vq_and_reset ,
547613 .enable_vq_after_reset = vp_modern_enable_vq_after_reset ,
614+ .create_avq = vp_modern_create_avq ,
615+ .destroy_avq = vp_modern_destroy_avq ,
548616};
549617
550618static const struct virtio_config_ops virtio_pci_config_ops = {
@@ -565,6 +633,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
565633 .get_shm_region = vp_get_shm_region ,
566634 .disable_vq_and_reset = vp_modern_disable_vq_and_reset ,
567635 .enable_vq_after_reset = vp_modern_enable_vq_after_reset ,
636+ .create_avq = vp_modern_create_avq ,
637+ .destroy_avq = vp_modern_destroy_avq ,
568638};
569639
570640/* the PCI probing function */
@@ -588,6 +658,7 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev)
588658 vp_dev -> config_vector = vp_config_vector ;
589659 vp_dev -> setup_vq = setup_vq ;
590660 vp_dev -> del_vq = del_vq ;
661+ vp_dev -> is_avq = vp_is_avq ;
591662 vp_dev -> isr = mdev -> isr ;
592663 vp_dev -> vdev .id = mdev -> id ;
593664
0 commit comments