virtio: find_vqs/del_vqs virtio operations
Subsystems (13)
A message that is not in the archive (sent off-list or not yet received): [email protected]
Michael S. Tsirkin
maintainerPATCH 1/3 virtio: find_vqs/del_vqs virtio operations
This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
--- drivers/block/virtio_blk.c | 11 +++--- drivers/char/hw_random/virtio-rng.c | 11 +++--- drivers/char/virtio_console.c | 27 ++++++-------- drivers/lguest/lguest_device.c | 49 +++++++++++++++++++++++++- drivers/net/virtio_net.c | 47 +++++++++++--------------- drivers/s390/kvm/kvm_virtio.c | 64 +++++++++++++++++++++++++++++++++- drivers/virtio/virtio_balloon.c | 31 ++++++++--------- drivers/virtio/virtio_pci.c | 43 +++++++++++++++++++---- include/linux/virtio_config.h | 29 +++++++++++----- 9 files changed, 222 insertions(+), 90 deletions(-)
drivers/block/virtio_blk.c +5 -6
@@ -197,6 +197,7 @@ static int virtblk_probe(struct virtio_device *vdev)u64 cap;u32 v;u32 blk_size, sg_elems; +virtqueue_callback *callback[] = { blk_done };if (index_to_minor (index) >=1 <<MINORBITS )return -ENOSPC ;
@@ -224,11 +225,9 @@ static int virtblk_probe(struct virtio_device *vdev)sg_init_table (vblk->sg, vblk->sg_elems);/* We expect one virtqueue, for output. */ - vblk->vq = vdev->config->find_vq (vdev,0 , blk_done); -if (IS_ERR (vblk->vq)) { - err =PTR_ERR (vblk->vq); + err = vdev->config->find_vqs (vdev,1 , &vblk->vq, callback); +if (err) goto out_free_vblk; - } vblk->pool =mempool_create_kmalloc_pool (1 ,sizeof (struct virtblk_req ));if (!vblk->pool) {
@@ -323,7 +322,7 @@ out_put_disk: out_mempool:mempool_destroy (vblk->pool); out_free_vq: - vdev->config->del_vq (vblk->vq); + vdev->config->del_vqs (vdev); out_free_vblk:kfree (vblk); out:
@@ -344,7 +343,7 @@ static void virtblk_remove(struct virtio_device *vdev)blk_cleanup_queue (vblk->disk->queue);put_disk (vblk->disk);mempool_destroy (vblk->pool); - vdev->config->del_vq (vblk->vq); + vdev->config->del_vqs (vdev);kfree (vblk); }
drivers/char/hw_random/virtio-rng.c +6 -5
@@ -91,16 +91,17 @@ static struct hwrng virtio_hwrng = {static int virtrng_probe (struct virtio_device *vdev) { +virtqueue_callback *callback[] = { random_recv_done };int err;/* We expect a single virtqueue. */ - vq = vdev->config->find_vq (vdev,0 , random_recv_done); -if (IS_ERR (vq)) -return PTR_ERR (vq); + err = vdev->config->find_vqs (vdev,1 , &vq, callback); +if (err) +return err; err =hwrng_register (&virtio_hwrng);if (err) { - vdev->config->del_vq (vq); + vdev->config->del_vqs (vdev);return err; }
@@ -112,7 +113,7 @@ static void virtrng_remove(struct virtio_device *vdev) { vdev->config->reset (vdev);hwrng_unregister (&virtio_hwrng); - vdev->config->del_vq (vq); + vdev->config->del_vqs (vdev); }static struct virtio_device_id id_table[] = {
drivers/char/virtio_console.c +12 -15
@@ -188,6 +188,8 @@ static void hvc_handle_input(struct virtqueue *vq)* Finally we put our input buffer in the input queue, ready to receive. */ static int __devinit virtcons_probe (struct virtio_device *dev) { +struct virtqueue *vqs[2 ]; +virtqueue_callback *callbacks[2 ];int err; vdev = dev;
@@ -199,20 +201,17 @@ static int __devinit virtcons_probe(struct virtio_device *dev) goto fail; } -/* Find the input queue. */ +/* Find the queues. */ /* FIXME: This is why we want to wean off hvc: we do nothing * when input comes in. */ - in_vq = vdev->config->find_vq (vdev,0 , hvc_handle_input); -if (IS_ERR (in_vq)) { - err =PTR_ERR (in_vq); + callbacks[0 ] = hvc_handle_input; + callbacks[1 ] =NULL ; + err = vdev->config->find_vqs (vdev,2 , vqs, callbacks); +if (err) goto free; - } - out_vq = vdev->config->find_vq (vdev,1 ,NULL ); -if (IS_ERR (out_vq)) { - err =PTR_ERR (out_vq); - goto free_in_vq; - } + in_vq = vqs[0 ]; + out_vq = vqs[1 ];/* Start using the new console output. */ virtio_cons.get_chars = get_chars;
@@ -233,17 +232,15 @@ static int __devinit virtcons_probe(struct virtio_device *dev) hvc =hvc_alloc (0 ,0 , &virtio_cons,PAGE_SIZE );if (IS_ERR (hvc)) { err =PTR_ERR (hvc); - goto free_out_vq; + goto free_vqs; }/* Register the input buffer the first time. */ add_inbuf ();return 0 ; -free_out_vq: - vdev->config->del_vq (out_vq); -free_in_vq: - vdev->config->del_vq (in_vq); +free_vqs: + vdev->config->del_vqs (vdev); free:kfree (inbuf); fail:
drivers/lguest/lguest_device.c +47 -2
67 lines not on this page · raw message
drivers/net/virtio_net.c +20 -27
81 lines not on this page · raw message
drivers/s390/kvm/kvm_virtio.c +62 -2
82 lines not on this page · raw message
drivers/virtio/virtio_balloon.c +14 -17
@@ -204,6 +204,8 @@ static int balloon(void *_vballoon)static int virtballoon_probe (struct virtio_device *vdev) {struct virtio_balloon *vb; +struct virtqueue *vqs[2 ]; +virtqueue_callback *callbacks[2 ];int err; vdev->priv = vb =kmalloc (sizeof (*vb),GFP_KERNEL );
@@ -218,22 +220,20 @@ static int virtballoon_probe(struct virtio_device *vdev) vb->vdev = vdev;/* We expect two virtqueues. */ - vb->inflate_vq = vdev->config->find_vq (vdev,0 , balloon_ack); -if (IS_ERR (vb->inflate_vq)) { - err =PTR_ERR (vb->inflate_vq); - goto out_free_vb; - } + callbacks[0 ] = balloon_ack; + callbacks[1 ] = balloon_ack; - vb->deflate_vq = vdev->config->find_vq (vdev,1 , balloon_ack); -if (IS_ERR (vb->deflate_vq)) { - err =PTR_ERR (vb->deflate_vq); - goto out_del_inflate_vq; - } + err = vdev->config->find_vqs (vdev,2 , vqs, callbacks); +if (err) + goto out_free_vb; + + vb->inflate_vq = vqs[0 ]; + vb->deflate_vq = vqs[1 ]; vb->thread =kthread_run (balloon, vb,"vballoon" );if (IS_ERR (vb->thread)) { err =PTR_ERR (vb->thread); - goto out_del_deflate_vq; + goto out_del_vqs; } vb->tell_host_first
@@ -241,10 +241,8 @@ static int virtballoon_probe(struct virtio_device *vdev)return 0 ; -out_del_deflate_vq: - vdev->config->del_vq (vb->deflate_vq); -out_del_inflate_vq: - vdev->config->del_vq (vb->inflate_vq); +out_del_vqs: + vdev->config->del_vqs (vdev); out_free_vb:kfree (vb); out:
@@ -264,8 +262,7 @@ static void virtballoon_remove(struct virtio_device *vdev)/* Now we reset the device so we can clean up the queues. */ vdev->config->reset (vdev); - vdev->config->del_vq (vb->deflate_vq); - vdev->config->del_vq (vb->inflate_vq); + vdev->config->del_vqs (vdev);kfree (vb); }
drivers/virtio/virtio_pci.c +36 -7
61 lines not on this page · raw message
include/linux/virtio_config.h +20 -9
@@ -49,15 +49,25 @@* @set_status: write the status byte * vdev: the virtio_device * status: the new status byte +* @request_vqs: request the specified number of virtqueues +* vdev: the virtio_device +* max_vqs: the max number of virtqueues we want +* If supplied, must call before any virtqueues are instantiated. +* To modify the max number of virtqueues after request_vqs has been +* called, call free_vqs and then request_vqs with a new value. +* @free_vqs: cleanup resources allocated by request_vqs +* vdev: the virtio_device +* If supplied, must call after all virtqueues have been deleted. * @reset: reset the device * vdev: the virtio device * After this, status and feature negotiation must be done again -* @find_vq: find a virtqueue and instantiate it. +* @find_vqs: find virtqueues and instantiate them. * vdev: the virtio_device -* index: the 0-based virtqueue number in case there's more than one. -* callback: the virqtueue callback -* Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). -* @del_vq: free a virtqueue found by find_vq(). +* nvqs: the number of virtqueues to find +* vqs: on success, includes new virtqueues +* callbacks: array of callbacks, for each virtqueue +* Returns 0 on success or error status +* @del_vqs: free virtqueues found by find_vqs(). * @get_features: get the array of feature bits for this device. * vdev: the virtio_device * Returns the first 32 feature bits (all we currently need).
@@ -66,6 +76,7 @@* This gives the final feature bits for the device: it can change * the dev->feature bits if it wants. */ +typedef void virtqueue_callback (struct virtqueue *);struct virtio_config_ops { void (*get)(struct virtio_device *vdev, unsigned offset,
@@ -75,10 +86,10 @@ struct virtio_config_opsu8 (*get_status)(struct virtio_device *vdev);void (*set_status)(struct virtio_device *vdev,u8 status);void (*reset)(struct virtio_device *vdev); -struct virtqueue *(*find_vq)(struct virtio_device *vdev, -unsigned index, -void (*callback)(struct virtqueue *)); -void (*del_vq)(struct virtqueue *vq); +int (*find_vqs)(struct virtio_device *,unsigned nvqs, +struct virtqueue *vqs[], +virtqueue_callback *callbacks[]); +void (*del_vqs)(struct virtio_device *);u32 (*get_features)(struct virtio_device *vdev);void (*finalize_features)(struct virtio_device *vdev); };
Signature · 1 line
1.6.3.rc3.1.g830204
Michael S. Tsirkin
maintainerPATCH 1/3 virtio: find_vqs/del_vqs virtio operations
In reply to a message not in the archiveThis replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
--- drivers/block/virtio_blk.c | 11 +++--- drivers/char/hw_random/virtio-rng.c | 11 +++--- drivers/char/virtio_console.c | 27 ++++++-------- drivers/lguest/lguest_device.c | 49 +++++++++++++++++++++++++- drivers/net/virtio_net.c | 47 +++++++++++--------------- drivers/s390/kvm/kvm_virtio.c | 64 +++++++++++++++++++++++++++++++++- drivers/virtio/virtio_balloon.c | 31 ++++++++--------- drivers/virtio/virtio_pci.c | 43 +++++++++++++++++++---- include/linux/virtio_config.h | 29 +++++++++++----- 9 files changed, 222 insertions(+), 90 deletions(-)
drivers/block/virtio_blk.c +5 -6
@@ -197,6 +197,7 @@ static int virtblk_probe(struct virtio_device *vdev)u64 cap;u32 v;u32 blk_size, sg_elems; +virtqueue_callback *callback[] = { blk_done };if (index_to_minor (index) >=1 <<MINORBITS )return -ENOSPC ;
@@ -224,11 +225,9 @@ static int virtblk_probe(struct virtio_device *vdev)sg_init_table (vblk->sg, vblk->sg_elems);/* We expect one virtqueue, for output. */ - vblk->vq = vdev->config->find_vq (vdev,0 , blk_done); -if (IS_ERR (vblk->vq)) { - err =PTR_ERR (vblk->vq); + err = vdev->config->find_vqs (vdev,1 , &vblk->vq, callback); +if (err) goto out_free_vblk; - } vblk->pool =mempool_create_kmalloc_pool (1 ,sizeof (struct virtblk_req ));if (!vblk->pool) {
@@ -323,7 +322,7 @@ out_put_disk: out_mempool:mempool_destroy (vblk->pool); out_free_vq: - vdev->config->del_vq (vblk->vq); + vdev->config->del_vqs (vdev); out_free_vblk:kfree (vblk); out:
@@ -344,7 +343,7 @@ static void virtblk_remove(struct virtio_device *vdev)blk_cleanup_queue (vblk->disk->queue);put_disk (vblk->disk);mempool_destroy (vblk->pool); - vdev->config->del_vq (vblk->vq); + vdev->config->del_vqs (vdev);kfree (vblk); }
drivers/char/hw_random/virtio-rng.c +6 -5
@@ -91,16 +91,17 @@ static struct hwrng virtio_hwrng = {static int virtrng_probe (struct virtio_device *vdev) { +virtqueue_callback *callback[] = { random_recv_done };int err;/* We expect a single virtqueue. */ - vq = vdev->config->find_vq (vdev,0 , random_recv_done); -if (IS_ERR (vq)) -return PTR_ERR (vq); + err = vdev->config->find_vqs (vdev,1 , &vq, callback); +if (err) +return err; err =hwrng_register (&virtio_hwrng);if (err) { - vdev->config->del_vq (vq); + vdev->config->del_vqs (vdev);return err; }
@@ -112,7 +113,7 @@ static void virtrng_remove(struct virtio_device *vdev) { vdev->config->reset (vdev);hwrng_unregister (&virtio_hwrng); - vdev->config->del_vq (vq); + vdev->config->del_vqs (vdev); }static struct virtio_device_id id_table[] = {
drivers/char/virtio_console.c +12 -15
@@ -188,6 +188,8 @@ static void hvc_handle_input(struct virtqueue *vq)* Finally we put our input buffer in the input queue, ready to receive. */ static int __devinit virtcons_probe (struct virtio_device *dev) { +struct virtqueue *vqs[2 ]; +virtqueue_callback *callbacks[2 ];int err; vdev = dev;
@@ -199,20 +201,17 @@ static int __devinit virtcons_probe(struct virtio_device *dev) goto fail; } -/* Find the input queue. */ +/* Find the queues. */ /* FIXME: This is why we want to wean off hvc: we do nothing * when input comes in. */ - in_vq = vdev->config->find_vq (vdev,0 , hvc_handle_input); -if (IS_ERR (in_vq)) { - err =PTR_ERR (in_vq); + callbacks[0 ] = hvc_handle_input; + callbacks[1 ] =NULL ; + err = vdev->config->find_vqs (vdev,2 , vqs, callbacks); +if (err) goto free; - } - out_vq = vdev->config->find_vq (vdev,1 ,NULL ); -if (IS_ERR (out_vq)) { - err =PTR_ERR (out_vq); - goto free_in_vq; - } + in_vq = vqs[0 ]; + out_vq = vqs[1 ];/* Start using the new console output. */ virtio_cons.get_chars = get_chars;
@@ -233,17 +232,15 @@ static int __devinit virtcons_probe(struct virtio_device *dev) hvc =hvc_alloc (0 ,0 , &virtio_cons,PAGE_SIZE );if (IS_ERR (hvc)) { err =PTR_ERR (hvc); - goto free_out_vq; + goto free_vqs; }/* Register the input buffer the first time. */ add_inbuf ();return 0 ; -free_out_vq: - vdev->config->del_vq (out_vq); -free_in_vq: - vdev->config->del_vq (in_vq); +free_vqs: + vdev->config->del_vqs (vdev); free:kfree (inbuf); fail:
drivers/lguest/lguest_device.c +47 -2
67 lines not on this page · raw message
drivers/net/virtio_net.c +20 -27
81 lines not on this page · raw message
drivers/s390/kvm/kvm_virtio.c +62 -2
82 lines not on this page · raw message
drivers/virtio/virtio_balloon.c +14 -17
@@ -204,6 +204,8 @@ static int balloon(void *_vballoon)static int virtballoon_probe (struct virtio_device *vdev) {struct virtio_balloon *vb; +struct virtqueue *vqs[2 ]; +virtqueue_callback *callbacks[2 ];int err; vdev->priv = vb =kmalloc (sizeof (*vb),GFP_KERNEL );
@@ -218,22 +220,20 @@ static int virtballoon_probe(struct virtio_device *vdev) vb->vdev = vdev;/* We expect two virtqueues. */ - vb->inflate_vq = vdev->config->find_vq (vdev,0 , balloon_ack); -if (IS_ERR (vb->inflate_vq)) { - err =PTR_ERR (vb->inflate_vq); - goto out_free_vb; - } + callbacks[0 ] = balloon_ack; + callbacks[1 ] = balloon_ack; - vb->deflate_vq = vdev->config->find_vq (vdev,1 , balloon_ack); -if (IS_ERR (vb->deflate_vq)) { - err =PTR_ERR (vb->deflate_vq); - goto out_del_inflate_vq; - } + err = vdev->config->find_vqs (vdev,2 , vqs, callbacks); +if (err) + goto out_free_vb; + + vb->inflate_vq = vqs[0 ]; + vb->deflate_vq = vqs[1 ]; vb->thread =kthread_run (balloon, vb,"vballoon" );if (IS_ERR (vb->thread)) { err =PTR_ERR (vb->thread); - goto out_del_deflate_vq; + goto out_del_vqs; } vb->tell_host_first
@@ -241,10 +241,8 @@ static int virtballoon_probe(struct virtio_device *vdev)return 0 ; -out_del_deflate_vq: - vdev->config->del_vq (vb->deflate_vq); -out_del_inflate_vq: - vdev->config->del_vq (vb->inflate_vq); +out_del_vqs: + vdev->config->del_vqs (vdev); out_free_vb:kfree (vb); out:
@@ -264,8 +262,7 @@ static void virtballoon_remove(struct virtio_device *vdev)/* Now we reset the device so we can clean up the queues. */ vdev->config->reset (vdev); - vdev->config->del_vq (vb->deflate_vq); - vdev->config->del_vq (vb->inflate_vq); + vdev->config->del_vqs (vdev);kfree (vb); }
drivers/virtio/virtio_pci.c +36 -7
61 lines not on this page · raw message
include/linux/virtio_config.h +20 -9
@@ -49,15 +49,25 @@* @set_status: write the status byte * vdev: the virtio_device * status: the new status byte +* @request_vqs: request the specified number of virtqueues +* vdev: the virtio_device +* max_vqs: the max number of virtqueues we want +* If supplied, must call before any virtqueues are instantiated. +* To modify the max number of virtqueues after request_vqs has been +* called, call free_vqs and then request_vqs with a new value. +* @free_vqs: cleanup resources allocated by request_vqs +* vdev: the virtio_device +* If supplied, must call after all virtqueues have been deleted. * @reset: reset the device * vdev: the virtio device * After this, status and feature negotiation must be done again -* @find_vq: find a virtqueue and instantiate it. +* @find_vqs: find virtqueues and instantiate them. * vdev: the virtio_device -* index: the 0-based virtqueue number in case there's more than one. -* callback: the virqtueue callback -* Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). -* @del_vq: free a virtqueue found by find_vq(). +* nvqs: the number of virtqueues to find +* vqs: on success, includes new virtqueues +* callbacks: array of callbacks, for each virtqueue +* Returns 0 on success or error status +* @del_vqs: free virtqueues found by find_vqs(). * @get_features: get the array of feature bits for this device. * vdev: the virtio_device * Returns the first 32 feature bits (all we currently need).
@@ -66,6 +76,7 @@* This gives the final feature bits for the device: it can change * the dev->feature bits if it wants. */ +typedef void virtqueue_callback (struct virtqueue *);struct virtio_config_ops { void (*get)(struct virtio_device *vdev, unsigned offset,
@@ -75,10 +86,10 @@ struct virtio_config_opsu8 (*get_status)(struct virtio_device *vdev);void (*set_status)(struct virtio_device *vdev,u8 status);void (*reset)(struct virtio_device *vdev); -struct virtqueue *(*find_vq)(struct virtio_device *vdev, -unsigned index, -void (*callback)(struct virtqueue *)); -void (*del_vq)(struct virtqueue *vq); +int (*find_vqs)(struct virtio_device *,unsigned nvqs, +struct virtqueue *vqs[], +virtqueue_callback *callbacks[]); +void (*del_vqs)(struct virtio_device *);u32 (*get_features)(struct virtio_device *vdev);void (*finalize_features)(struct virtio_device *vdev); };
Signature · 1 line
1.6.3.rc3.1.g830204
Quoted 3 lines · Michael S. Tsirkin
This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
Hmm, I have a similar need for a dev to vq mapping (debugging stats). How's this as a common basis?
Thanks,
Rusty.
virtio: add names to virtqueue struct, mapping from devices to queues.
Add a linked list of all virtqueues for a virtio device: this helps for debugging and is also needed for upcoming interface change.
Also, add a "name" field for clearer debug messages.
--- drivers/block/virtio_blk.c | 2 +- drivers/char/hw_random/virtio-rng.c | 2 +- drivers/char/virtio_console.c | 4 ++-- drivers/lguest/lguest_device.c | 5 +++-- drivers/net/virtio_net.c | 6 +++--- drivers/s390/kvm/kvm_virtio.c | 7 ++++--- drivers/virtio/virtio.c | 2 ++ drivers/virtio/virtio_balloon.c | 4 ++-- drivers/virtio/virtio_pci.c | 5 +++-- drivers/virtio/virtio_ring.c | 25 +++++++++++++++++++------ include/linux/virtio.h | 12 ++++++++---- include/linux/virtio_config.h | 6 ++++-- include/linux/virtio_ring.h | 3 ++- net/9p/trans_virtio.c | 2 +- 14 files changed, 55 insertions(+), 30 deletions(-)
drivers/block/virtio_blk.c +1 -1
@@ -224,7 +224,7 @@ static int virtblk_probe(struct virtio_dsg_init_table (vblk->sg, vblk->sg_elems);/* We expect one virtqueue, for output. */ - vblk->vq = vdev->config->find_vq (vdev,0 , blk_done); + vblk->vq = vdev->config->find_vq (vdev,0 , blk_done,"requests" );if (IS_ERR (vblk->vq)) { err =PTR_ERR (vblk->vq); goto out_free_vblk;
drivers/char/hw_random/virtio-rng.c +1 -1
@@ -94,7 +94,7 @@ static int virtrng_probe(struct virtio_dint err;/* We expect a single virtqueue. */ - vq = vdev->config->find_vq (vdev,0 , random_recv_done); + vq = vdev->config->find_vq (vdev,0 , random_recv_done,"input" );if (IS_ERR (vq))return PTR_ERR (vq);
drivers/char/virtio_console.c +2 -2
@@ -202,13 +202,13 @@ static int __devinit virtcons_probe(stru/* Find the input queue. */ /* FIXME: This is why we want to wean off hvc: we do nothing * when input comes in. */ - in_vq = vdev->config->find_vq (vdev,0 , hvc_handle_input); + in_vq = vdev->config->find_vq (vdev,0 , hvc_handle_input,"input" );if (IS_ERR (in_vq)) { err =PTR_ERR (in_vq); goto free; } - out_vq = vdev->config->find_vq (vdev,1 ,NULL ); + out_vq = vdev->config->find_vq (vdev,1 ,NULL ,"output" );if (IS_ERR (out_vq)) { err =PTR_ERR (out_vq); goto free_in_vq;
drivers/lguest/lguest_device.c +3 -2
@@ -228,7 +228,8 @@ extern void lguest_setup_irq(unsigned in* function. */ static struct virtqueue *lg_find_vq (struct virtio_device *vdev,unsigned index, -void (*callback)(struct virtqueue *vq)) +void (*callback)(struct virtqueue *vq), +const char *name) {struct lguest_device *ldev =to_lgdev (vdev);struct lguest_vq_info *lvq;
@@ -263,7 +264,7 @@ static struct virtqueue *lg_find_vq(stru/* OK, tell virtio_ring.c to set up a virtqueue now we know its size * and we've got a pointer to its pages. */ vq =vring_new_virtqueue (lvq->config.num,LGUEST_VRING_ALIGN , - vdev, lvq->pages, lg_notify, callback); + vdev, lvq->pages, lg_notify, callback, name);if (!vq) { err = -ENOMEM ; goto unmap;
drivers/net/virtio_net.c +3 -3
@@ -902,20 +902,20 @@ static int virtnet_probe(struct virtio_d vi->mergeable_rx_bufs = true;/* We expect two virtqueues, receive then send. */ - vi->rvq = vdev->config->find_vq (vdev,0 , skb_recv_done); + vi->rvq = vdev->config->find_vq (vdev,0 , skb_recv_done,"input" );if (IS_ERR (vi->rvq)) { err =PTR_ERR (vi->rvq); goto free; } - vi->svq = vdev->config->find_vq (vdev,1 , skb_xmit_done); + vi->svq = vdev->config->find_vq (vdev,1 , skb_xmit_done,"output" );if (IS_ERR (vi->svq)) { err =PTR_ERR (vi->svq); goto free_recv; }if (virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VQ )) { - vi->cvq = vdev->config->find_vq (vdev,2 ,NULL ); + vi->cvq = vdev->config->find_vq (vdev,2 ,NULL ,"control" );if (IS_ERR (vi->cvq)) { err =PTR_ERR (vi->svq); goto free_send;
drivers/s390/kvm/kvm_virtio.c +4 -3
@@ -173,8 +173,9 @@ static void kvm_notify(struct virtqueue* this device and sets it up. */ static struct virtqueue *kvm_find_vq (struct virtio_device *vdev, -unsigned index, -void (*callback)(struct virtqueue *vq)) +unsigned index, +void (*callback)(struct virtqueue *vq), +const char *name) {struct kvm_device *kdev =to_kvmdev (vdev);struct kvm_vqconfig *config;
@@ -194,7 +195,7 @@ static struct virtqueue *kvm_find_vq(str vq =vring_new_virtqueue (config->num,KVM_S390_VIRTIO_RING_ALIGN , vdev, (void *) config->address, - kvm_notify, callback); + kvm_notify, callback, name);if (!vq) { err = -ENOMEM ; goto unmap;
drivers/virtio/virtio.c +2 -0
@@ -186,6 +186,8 @@ int register_virtio_device(struct virtio/* Acknowledge that we've seen the device. */ add_status (dev,VIRTIO_CONFIG_S_ACKNOWLEDGE ); +INIT_LIST_HEAD (&dev->vqs); +/* device_register() causes the bus infrastructure to look for a * matching driver. */ err =device_register (&dev->dev);
drivers/virtio/virtio_balloon.c +2 -2
@@ -218,13 +218,13 @@ static int virtballoon_probe(struct virt vb->vdev = vdev;/* We expect two virtqueues. */ - vb->inflate_vq = vdev->config->find_vq (vdev,0 , balloon_ack); + vb->inflate_vq = vdev->config->find_vq (vdev,0 , balloon_ack,"inflate" );if (IS_ERR (vb->inflate_vq)) { err =PTR_ERR (vb->inflate_vq); goto out_free_vb; } - vb->deflate_vq = vdev->config->find_vq (vdev,1 , balloon_ack); + vb->deflate_vq = vdev->config->find_vq (vdev,1 , balloon_ack,"deflate" );if (IS_ERR (vb->deflate_vq)) { err =PTR_ERR (vb->deflate_vq); goto out_del_inflate_vq;
drivers/virtio/virtio_pci.c +3 -2
@@ -208,7 +208,8 @@ static irqreturn_t vp_interrupt(int irq,/* the config->find_vq() implementation */ static struct virtqueue *vp_find_vq (struct virtio_device *vdev,unsigned index, -void (*callback)(struct virtqueue *vq)) +void (*callback)(struct virtqueue *vq), +const char *name) {struct virtio_pci_device *vp_dev =to_vp_device (vdev);struct virtio_pci_vq_info *info;
@@ -247,7 +248,7 @@ static struct virtqueue *vp_find_vq(stru/* create the vring */ vq =vring_new_virtqueue (info->num,VIRTIO_PCI_VRING_ALIGN , - vdev, info->queue, vp_notify, callback); + vdev, info->queue, vp_notify, callback, name);if (!vq) { err = -ENOMEM ; goto out_activate_queue;
drivers/virtio/virtio_ring.c +19 -6
@@ -23,21 +23,30 @@#ifdef DEBUG /* For development, we want to crash whenever the ring is screwed. */ -#define BAD_RING(_vq, fmt...) \ - do { dev_err(&(_vq)->vq.vdev->dev, fmt); BUG(); } while(0) +#define BAD_RING(_vq, fmt, args...) \ + do { \ + dev_err(&(_vq)->vq.vdev->dev, \ + "%s:"fmt, (_vq)->vq.name, ##args); \ + BUG(); \ + } while (0)/* Caller is supposed to guarantee no reentry. */ #define START_USE (_vq) \ do { \ if ((_vq)->in_use) \ - panic("in_use = %i\n", (_vq)->in_use); \ + panic("%s:in_use = %i\n", \ + (_vq)->vq.name, (_vq)->in_use); \ (_vq)->in_use = __LINE__; \ mb(); \ } while (0)#define END_USE (_vq) \ do { BUG_ON(!(_vq)->in_use); (_vq)->in_use = 0; mb(); } while(0)#else -#define BAD_RING(_vq, fmt...) \ - do { dev_err(&_vq->vq.vdev->dev, fmt); (_vq)->broken = true; } while(0) +#define BAD_RING(_vq, fmt, args...) \ + do { \ + dev_err(&_vq->vq.vdev->dev, \ + "%s:"fmt, (_vq)->vq.name, ##args); \ + (_vq)->broken = true; \ + } while(0)#define START_USE (vq)#define END_USE (vq)#endif
@@ -284,7 +293,8 @@ struct virtqueue *vring_new_virtqueue(unstruct virtio_device *vdev, void *pages, void (*notify)(struct virtqueue *), - void (*callback)(struct virtqueue *)) + void (*callback)(struct virtqueue *), + const char *name) { struct vring_virtqueue *vq;unsigned int i;
@@ -303,10 +313,12 @@ struct virtqueue *vring_new_virtqueue(un vq->vq.callback = callback; vq->vq.vdev = vdev; vq->vq.vq_ops = &vring_vq_ops; + vq->vq.name = name; vq->notify = notify; vq->broken = false; vq->last_used_idx =0 ; vq->num_added =0 ; +list_add_tail (&vq->vq.list, &vdev->vqs);#ifdef DEBUG vq->in_use = false;#endif
@@ -327,6 +339,7 @@ EXPORT_SYMBOL_GPL(vring_new_virtqueue);void vring_del_virtqueue (struct virtqueue *vq) { +list_del (&vq->list);kfree (to_vvq (vq)); }EXPORT_SYMBOL_GPL (vring_del_virtqueue);
include/linux/virtio.h +8 -4
@@ -10,14 +10,17 @@/** * virtqueue - a queue to register buffers for sending or receiving. +* @list: the chain of virtqueues for this device * @callback: the function to call when buffers are consumed (can be NULL). +* @name: the name of this virtqueue (mainly for debugging) * @vdev: the virtio device this queue was created for. * @vq_ops: the operations for this virtqueue (see below). * @priv: a pointer for the virtqueue implementation to use. */ -struct virtqueue -{ +struct virtqueue { +struct list_head list;void (*callback)(struct virtqueue *vq); +const char *name;struct virtio_device *vdev;struct virtqueue_ops *vq_ops;void *priv;
@@ -76,15 +79,16 @@ struct virtqueue_ops {* @dev: underlying device. * @id: the device type identification (used to match it with a driver). * @config: the configuration ops for this device. +* @vqs: the list of virtqueues for this device. * @features: the features supported by both driver and device. * @priv: private pointer for the driver's use. */ -struct virtio_device -{ +struct virtio_device {int index;struct device dev;struct virtio_device_id id;struct virtio_config_ops *config; +struct list_head vqs;/* Note that this is a Linux set_bit-style bitmap. */ unsigned long features[1 ];void *priv;
include/linux/virtio_config.h +4 -2
@@ -55,7 +55,8 @@* @find_vq: find a virtqueue and instantiate it. * vdev: the virtio_device * index: the 0-based virtqueue number in case there's more than one. -* callback: the virqtueue callback +* callback: the virtqueue callback +* name: the virtqueue name (mainly for debugging) * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). * @del_vq: free a virtqueue found by find_vq(). * @get_features: get the array of feature bits for this device.
@@ -77,7 +78,8 @@ struct virtio_config_opsvoid (*reset)(struct virtio_device *vdev);struct virtqueue *(*find_vq)(struct virtio_device *vdev,unsigned index, -void (*callback)(struct virtqueue *)); +void (*callback)(struct virtqueue *), +const char *name);void (*del_vq)(struct virtqueue *vq);u32 (*get_features)(struct virtio_device *vdev);void (*finalize_features)(struct virtio_device *vdev);
include/linux/virtio_ring.h +2 -1
@@ -119,7 +119,8 @@ struct virtqueue *vring_new_virtqueue(unstruct virtio_device *vdev, void *pages, void (*notify)(struct virtqueue *vq), - void (*callback)(struct virtqueue *vq)); + void (*callback)(struct virtqueue *vq), + const char *name);void vring_del_virtqueue (struct virtqueue *vq);/* Filter out transport-specific feature bits. */ void vring_transport_features (struct virtio_device *vdev);
net/9p/trans_virtio.c +1 -1
@@ -245,7 +245,7 @@ static int p9_virtio_probe(struct virtio chan->vdev = vdev;/* We expect one virtqueue, for requests. */ - chan->vq = vdev->config->find_vq (vdev,0 , req_done); + chan->vq = vdev->config->find_vq (vdev,0 , req_done,"requests" );if (IS_ERR (chan->vq)) { err =PTR_ERR (chan->vq); goto out_free_vq;
Quoted 3 lines · Michael S. Tsirkin
This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
Hmm, I have a similar need for a dev to vq mapping (debugging stats). How's this as a common basis?
Thanks,
Rusty.
virtio: add names to virtqueue struct, mapping from devices to queues.
Add a linked list of all virtqueues for a virtio device: this helps for debugging and is also needed for upcoming interface change.
Also, add a "name" field for clearer debug messages.
--- drivers/block/virtio_blk.c | 2 +- drivers/char/hw_random/virtio-rng.c | 2 +- drivers/char/virtio_console.c | 4 ++-- drivers/lguest/lguest_device.c | 5 +++-- drivers/net/virtio_net.c | 6 +++--- drivers/s390/kvm/kvm_virtio.c | 7 ++++--- drivers/virtio/virtio.c | 2 ++ drivers/virtio/virtio_balloon.c | 4 ++-- drivers/virtio/virtio_pci.c | 5 +++-- drivers/virtio/virtio_ring.c | 25 +++++++++++++++++++------ include/linux/virtio.h | 12 ++++++++---- include/linux/virtio_config.h | 6 ++++-- include/linux/virtio_ring.h | 3 ++- net/9p/trans_virtio.c | 2 +- 14 files changed, 55 insertions(+), 30 deletions(-)
drivers/block/virtio_blk.c +1 -1
@@ -224,7 +224,7 @@ static int virtblk_probe(struct virtio_dsg_init_table (vblk->sg, vblk->sg_elems);/* We expect one virtqueue, for output. */ - vblk->vq = vdev->config->find_vq (vdev,0 , blk_done); + vblk->vq = vdev->config->find_vq (vdev,0 , blk_done,"requests" );if (IS_ERR (vblk->vq)) { err =PTR_ERR (vblk->vq); goto out_free_vblk;
drivers/char/hw_random/virtio-rng.c +1 -1
@@ -94,7 +94,7 @@ static int virtrng_probe(struct virtio_dint err;/* We expect a single virtqueue. */ - vq = vdev->config->find_vq (vdev,0 , random_recv_done); + vq = vdev->config->find_vq (vdev,0 , random_recv_done,"input" );if (IS_ERR (vq))return PTR_ERR (vq);
drivers/char/virtio_console.c +2 -2
@@ -202,13 +202,13 @@ static int __devinit virtcons_probe(stru/* Find the input queue. */ /* FIXME: This is why we want to wean off hvc: we do nothing * when input comes in. */ - in_vq = vdev->config->find_vq (vdev,0 , hvc_handle_input); + in_vq = vdev->config->find_vq (vdev,0 , hvc_handle_input,"input" );if (IS_ERR (in_vq)) { err =PTR_ERR (in_vq); goto free; } - out_vq = vdev->config->find_vq (vdev,1 ,NULL ); + out_vq = vdev->config->find_vq (vdev,1 ,NULL ,"output" );if (IS_ERR (out_vq)) { err =PTR_ERR (out_vq); goto free_in_vq;
drivers/lguest/lguest_device.c +3 -2
@@ -228,7 +228,8 @@ extern void lguest_setup_irq(unsigned in* function. */ static struct virtqueue *lg_find_vq (struct virtio_device *vdev,unsigned index, -void (*callback)(struct virtqueue *vq)) +void (*callback)(struct virtqueue *vq), +const char *name) {struct lguest_device *ldev =to_lgdev (vdev);struct lguest_vq_info *lvq;
@@ -263,7 +264,7 @@ static struct virtqueue *lg_find_vq(stru/* OK, tell virtio_ring.c to set up a virtqueue now we know its size * and we've got a pointer to its pages. */ vq =vring_new_virtqueue (lvq->config.num,LGUEST_VRING_ALIGN , - vdev, lvq->pages, lg_notify, callback); + vdev, lvq->pages, lg_notify, callback, name);if (!vq) { err = -ENOMEM ; goto unmap;
drivers/net/virtio_net.c +3 -3
@@ -902,20 +902,20 @@ static int virtnet_probe(struct virtio_d vi->mergeable_rx_bufs = true;/* We expect two virtqueues, receive then send. */ - vi->rvq = vdev->config->find_vq (vdev,0 , skb_recv_done); + vi->rvq = vdev->config->find_vq (vdev,0 , skb_recv_done,"input" );if (IS_ERR (vi->rvq)) { err =PTR_ERR (vi->rvq); goto free; } - vi->svq = vdev->config->find_vq (vdev,1 , skb_xmit_done); + vi->svq = vdev->config->find_vq (vdev,1 , skb_xmit_done,"output" );if (IS_ERR (vi->svq)) { err =PTR_ERR (vi->svq); goto free_recv; }if (virtio_has_feature (vi->vdev,VIRTIO_NET_F_CTRL_VQ )) { - vi->cvq = vdev->config->find_vq (vdev,2 ,NULL ); + vi->cvq = vdev->config->find_vq (vdev,2 ,NULL ,"control" );if (IS_ERR (vi->cvq)) { err =PTR_ERR (vi->svq); goto free_send;
drivers/s390/kvm/kvm_virtio.c +4 -3
@@ -173,8 +173,9 @@ static void kvm_notify(struct virtqueue* this device and sets it up. */ static struct virtqueue *kvm_find_vq (struct virtio_device *vdev, -unsigned index, -void (*callback)(struct virtqueue *vq)) +unsigned index, +void (*callback)(struct virtqueue *vq), +const char *name) {struct kvm_device *kdev =to_kvmdev (vdev);struct kvm_vqconfig *config;
@@ -194,7 +195,7 @@ static struct virtqueue *kvm_find_vq(str vq =vring_new_virtqueue (config->num,KVM_S390_VIRTIO_RING_ALIGN , vdev, (void *) config->address, - kvm_notify, callback); + kvm_notify, callback, name);if (!vq) { err = -ENOMEM ; goto unmap;
drivers/virtio/virtio.c +2 -0
@@ -186,6 +186,8 @@ int register_virtio_device(struct virtio/* Acknowledge that we've seen the device. */ add_status (dev,VIRTIO_CONFIG_S_ACKNOWLEDGE ); +INIT_LIST_HEAD (&dev->vqs); +/* device_register() causes the bus infrastructure to look for a * matching driver. */ err =device_register (&dev->dev);
drivers/virtio/virtio_balloon.c +2 -2
@@ -218,13 +218,13 @@ static int virtballoon_probe(struct virt vb->vdev = vdev;/* We expect two virtqueues. */ - vb->inflate_vq = vdev->config->find_vq (vdev,0 , balloon_ack); + vb->inflate_vq = vdev->config->find_vq (vdev,0 , balloon_ack,"inflate" );if (IS_ERR (vb->inflate_vq)) { err =PTR_ERR (vb->inflate_vq); goto out_free_vb; } - vb->deflate_vq = vdev->config->find_vq (vdev,1 , balloon_ack); + vb->deflate_vq = vdev->config->find_vq (vdev,1 , balloon_ack,"deflate" );if (IS_ERR (vb->deflate_vq)) { err =PTR_ERR (vb->deflate_vq); goto out_del_inflate_vq;
drivers/virtio/virtio_pci.c +3 -2
@@ -208,7 +208,8 @@ static irqreturn_t vp_interrupt(int irq,/* the config->find_vq() implementation */ static struct virtqueue *vp_find_vq (struct virtio_device *vdev,unsigned index, -void (*callback)(struct virtqueue *vq)) +void (*callback)(struct virtqueue *vq), +const char *name) {struct virtio_pci_device *vp_dev =to_vp_device (vdev);struct virtio_pci_vq_info *info;
@@ -247,7 +248,7 @@ static struct virtqueue *vp_find_vq(stru/* create the vring */ vq =vring_new_virtqueue (info->num,VIRTIO_PCI_VRING_ALIGN , - vdev, info->queue, vp_notify, callback); + vdev, info->queue, vp_notify, callback, name);if (!vq) { err = -ENOMEM ; goto out_activate_queue;
drivers/virtio/virtio_ring.c +19 -6
@@ -23,21 +23,30 @@#ifdef DEBUG /* For development, we want to crash whenever the ring is screwed. */ -#define BAD_RING(_vq, fmt...) \ - do { dev_err(&(_vq)->vq.vdev->dev, fmt); BUG(); } while(0) +#define BAD_RING(_vq, fmt, args...) \ + do { \ + dev_err(&(_vq)->vq.vdev->dev, \ + "%s:"fmt, (_vq)->vq.name, ##args); \ + BUG(); \ + } while (0)/* Caller is supposed to guarantee no reentry. */ #define START_USE (_vq) \ do { \ if ((_vq)->in_use) \ - panic("in_use = %i\n", (_vq)->in_use); \ + panic("%s:in_use = %i\n", \ + (_vq)->vq.name, (_vq)->in_use); \ (_vq)->in_use = __LINE__; \ mb(); \ } while (0)#define END_USE (_vq) \ do { BUG_ON(!(_vq)->in_use); (_vq)->in_use = 0; mb(); } while(0)#else -#define BAD_RING(_vq, fmt...) \ - do { dev_err(&_vq->vq.vdev->dev, fmt); (_vq)->broken = true; } while(0) +#define BAD_RING(_vq, fmt, args...) \ + do { \ + dev_err(&_vq->vq.vdev->dev, \ + "%s:"fmt, (_vq)->vq.name, ##args); \ + (_vq)->broken = true; \ + } while(0)#define START_USE (vq)#define END_USE (vq)#endif
@@ -284,7 +293,8 @@ struct virtqueue *vring_new_virtqueue(unstruct virtio_device *vdev, void *pages, void (*notify)(struct virtqueue *), - void (*callback)(struct virtqueue *)) + void (*callback)(struct virtqueue *), + const char *name) { struct vring_virtqueue *vq;unsigned int i;
@@ -303,10 +313,12 @@ struct virtqueue *vring_new_virtqueue(un vq->vq.callback = callback; vq->vq.vdev = vdev; vq->vq.vq_ops = &vring_vq_ops; + vq->vq.name = name; vq->notify = notify; vq->broken = false; vq->last_used_idx =0 ; vq->num_added =0 ; +list_add_tail (&vq->vq.list, &vdev->vqs);#ifdef DEBUG vq->in_use = false;#endif
@@ -327,6 +339,7 @@ EXPORT_SYMBOL_GPL(vring_new_virtqueue);void vring_del_virtqueue (struct virtqueue *vq) { +list_del (&vq->list);kfree (to_vvq (vq)); }EXPORT_SYMBOL_GPL (vring_del_virtqueue);
include/linux/virtio.h +8 -4
@@ -10,14 +10,17 @@/** * virtqueue - a queue to register buffers for sending or receiving. +* @list: the chain of virtqueues for this device * @callback: the function to call when buffers are consumed (can be NULL). +* @name: the name of this virtqueue (mainly for debugging) * @vdev: the virtio device this queue was created for. * @vq_ops: the operations for this virtqueue (see below). * @priv: a pointer for the virtqueue implementation to use. */ -struct virtqueue -{ +struct virtqueue { +struct list_head list;void (*callback)(struct virtqueue *vq); +const char *name;struct virtio_device *vdev;struct virtqueue_ops *vq_ops;void *priv;
@@ -76,15 +79,16 @@ struct virtqueue_ops {* @dev: underlying device. * @id: the device type identification (used to match it with a driver). * @config: the configuration ops for this device. +* @vqs: the list of virtqueues for this device. * @features: the features supported by both driver and device. * @priv: private pointer for the driver's use. */ -struct virtio_device -{ +struct virtio_device {int index;struct device dev;struct virtio_device_id id;struct virtio_config_ops *config; +struct list_head vqs;/* Note that this is a Linux set_bit-style bitmap. */ unsigned long features[1 ];void *priv;
include/linux/virtio_config.h +4 -2
@@ -55,7 +55,8 @@* @find_vq: find a virtqueue and instantiate it. * vdev: the virtio_device * index: the 0-based virtqueue number in case there's more than one. -* callback: the virqtueue callback +* callback: the virtqueue callback +* name: the virtqueue name (mainly for debugging) * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). * @del_vq: free a virtqueue found by find_vq(). * @get_features: get the array of feature bits for this device.
@@ -77,7 +78,8 @@ struct virtio_config_opsvoid (*reset)(struct virtio_device *vdev);struct virtqueue *(*find_vq)(struct virtio_device *vdev,unsigned index, -void (*callback)(struct virtqueue *)); +void (*callback)(struct virtqueue *), +const char *name);void (*del_vq)(struct virtqueue *vq);u32 (*get_features)(struct virtio_device *vdev);void (*finalize_features)(struct virtio_device *vdev);
include/linux/virtio_ring.h +2 -1
@@ -119,7 +119,8 @@ struct virtqueue *vring_new_virtqueue(unstruct virtio_device *vdev, void *pages, void (*notify)(struct virtqueue *vq), - void (*callback)(struct virtqueue *vq)); + void (*callback)(struct virtqueue *vq), + const char *name);void vring_del_virtqueue (struct virtqueue *vq);/* Filter out transport-specific feature bits. */ void vring_transport_features (struct virtio_device *vdev);
net/9p/trans_virtio.c +1 -1
@@ -245,7 +245,7 @@ static int p9_virtio_probe(struct virtio chan->vdev = vdev;/* We expect one virtqueue, for requests. */ - chan->vq = vdev->config->find_vq (vdev,0 , req_done); + chan->vq = vdev->config->find_vq (vdev,0 , req_done,"requests" );if (IS_ERR (chan->vq)) { err =PTR_ERR (chan->vq); goto out_free_vq;
Michael S. Tsirkin
maintainerQuoted 7 lines · Rusty Russell
Quoted 3 lines · Michael S. Tsirkin
This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
Hmm, I have a similar need for a dev to vq mapping (debugging stats). How's this as a common basis?
This helps. Should I redo mine on top of this?
Quoted 11 lines
Thanks,
Rusty.virtio: add names to virtqueue struct, mapping from devices to queues.
Add a linked list of all virtqueues for a virtio device: this helps for debugging and is also needed for upcoming interface change.
Also, add a "name" field for clearer debug messages.
Signed-off-by Rusty Russell <[email protected]>
Yes, this will simplify supporting find_vqs.
Quoted 14 lines
drivers/virtio/virtio_ring.c +2
-0@@ -303,10 +313,12 @@ struct virtqueue *vring_new_virtqueue(un vq->vq.callback = callback; vq->vq.vdev = vdev; vq->vq.vq_ops = &vring_vq_ops; + vq->vq.name = name; vq->notify = notify; vq->broken = false; vq->last_used_idx =0 ; vq->num_added =0 ; +list_add_tail (&vq->vq.list, &vdev->vqs);#ifdef DEBUG vq->in_use = false;#endif
drivers/virtio/virtio_ring.c EXPORT_SYMBOL_GPL(vring_new_virtqueue); · line 345
Quoted 7 lines
drivers/virtio/virtio_ring.c +1
-0@@ -327,6 +339,7 @@ EXPORT_SYMBOL_GPL(vring_new_virtqueue);void vring_del_virtqueue (struct virtqueue *vq) { +list_del (&vq->list);kfree (to_vvq (vq)); }EXPORT_SYMBOL_GPL (vring_del_virtqueue);
I note lack of locking here. This is okay in practice as drivers don't really call find/del vq in parallel, but making this explicit with find_vqs will be best, yes?
Signature · 1 line
MST
Michael S. Tsirkin
maintainerQuoted 7 lines · Rusty Russell
Quoted 3 lines · Michael S. Tsirkin
This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
Hmm, I have a similar need for a dev to vq mapping (debugging stats). How's this as a common basis?
This helps. Should I redo mine on top of this?
Quoted 11 lines
Thanks,
Rusty.virtio: add names to virtqueue struct, mapping from devices to queues.
Add a linked list of all virtqueues for a virtio device: this helps for debugging and is also needed for upcoming interface change.
Also, add a "name" field for clearer debug messages.
Signed-off-by Rusty Russell <[email protected]>
Yes, this will simplify supporting find_vqs.
Quoted 14 lines
drivers/virtio/virtio_ring.c +2
-0@@ -303,10 +313,12 @@ struct virtqueue *vring_new_virtqueue(un vq->vq.callback = callback; vq->vq.vdev = vdev; vq->vq.vq_ops = &vring_vq_ops; + vq->vq.name = name; vq->notify = notify; vq->broken = false; vq->last_used_idx =0 ; vq->num_added =0 ; +list_add_tail (&vq->vq.list, &vdev->vqs);#ifdef DEBUG vq->in_use = false;#endif
drivers/virtio/virtio_ring.c EXPORT_SYMBOL_GPL(vring_new_virtqueue); · line 345
Quoted 7 lines
drivers/virtio/virtio_ring.c +1
-0@@ -327,6 +339,7 @@ EXPORT_SYMBOL_GPL(vring_new_virtqueue);void vring_del_virtqueue (struct virtqueue *vq) { +list_del (&vq->list);kfree (to_vvq (vq)); }EXPORT_SYMBOL_GPL (vring_del_virtqueue);
I note lack of locking here. This is okay in practice as drivers don't really call find/del vq in parallel, but making this explicit with find_vqs will be best, yes?
Signature · 1 line
MST
Quoted 10 lines · Michael S. Tsirkin
Quoted 7 lines · Rusty Russell
Quoted 3 lines · Michael S. Tsirkin
This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
Hmm, I have a similar need for a dev to vq mapping (debugging stats). How's this as a common basis?
This helps. Should I redo mine on top of this?
Yep, it should make your smaller as well.
Quoted 10 lines
drivers/virtio/virtio_ring.c EXPORT_SYMBOL_GPL(vring_new_virtqueue); · line 345
Quoted 6 lines
void
vring_del_virtqueue(struct virtqueue *vq)
{drivers/virtio/virtio_ring.c +1
-0+list_del (&vq->list);kfree (to_vvq (vq)); }EXPORT_SYMBOL_GPL (vring_del_virtqueue);I note lack of locking here. This is okay in practice as drivers don't really call find/del vq in parallel, but making this explicit with
find_vqswill be best, yes?
Yes, and in fact a rough look at your patch reveals that we don't actually need del_vq: now we track them, we can just do that as part of vdev destruction, right?
If you agree, please do that patch first, then do the find_vqs change on top of that.
Thanks!
Rusty.
Quoted 10 lines · Michael S. Tsirkin
Quoted 7 lines · Rusty Russell
Quoted 3 lines · Michael S. Tsirkin
This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations, and updates all drivers. This is needed for MSI support, because MSI needs to know the total number of vectors upfront.
Hmm, I have a similar need for a dev to vq mapping (debugging stats). How's this as a common basis?
This helps. Should I redo mine on top of this?
Yep, it should make your smaller as well.
Quoted 10 lines
drivers/virtio/virtio_ring.c EXPORT_SYMBOL_GPL(vring_new_virtqueue); · line 345
Quoted 6 lines
void
vring_del_virtqueue(struct virtqueue *vq)
{drivers/virtio/virtio_ring.c +1
-0+list_del (&vq->list);kfree (to_vvq (vq)); }EXPORT_SYMBOL_GPL (vring_del_virtqueue);I note lack of locking here. This is okay in practice as drivers don't really call find/del vq in parallel, but making this explicit with
find_vqswill be best, yes?
Yes, and in fact a rough look at your patch reveals that we don't actually need del_vq: now we track them, we can just do that as part of vdev destruction, right?
If you agree, please do that patch first, then do the find_vqs change on top of that.
Thanks!
Rusty.
Michael S. Tsirkin
maintainerQuoted 3 lines · Rusty Russell
Yes, and in fact a rough look at your patch reveals that we don't actually need
del_vq: now we track them, we can just do that as part of vdev destruction, right?
Let's assume that a driver encounters an error in probe after it calls find_vq. It would need a way to revert find_vq, won't it?
It seems to me that bus->remove does not get called on probe failure. Isn't that right?
Signature · 1 line
MST
Michael S. Tsirkin
maintainerQuoted 3 lines · Rusty Russell
Yes, and in fact a rough look at your patch reveals that we don't actually need
del_vq: now we track them, we can just do that as part of vdev destruction, right?
Let's assume that a driver encounters an error in probe after it calls find_vq. It would need a way to revert find_vq, won't it?
It seems to me that bus->remove does not get called on probe failure. Isn't that right?
Signature · 1 line
MST
Quoted 11 lines · Michael S. Tsirkin
Quoted 3 lines · Rusty Russell
Yes, and in fact a rough look at your patch reveals that we don't actually need
del_vq: now we track them, we can just do that as part of vdev destruction, right?Let's assume that a driver encounters an error in probe after it calls
find_vq. It would need a way to revertfind_vq, won't it?It seems to me that
bus->removedoes not get called on probe failure. Isn't that right?
Yep, I looked too fast.
Thanks,
Rusty.
Quoted 11 lines · Michael S. Tsirkin
Quoted 3 lines · Rusty Russell
Yes, and in fact a rough look at your patch reveals that we don't actually need
del_vq: now we track them, we can just do that as part of vdev destruction, right?Let's assume that a driver encounters an error in probe after it calls
find_vq. It would need a way to revertfind_vq, won't it?It seems to me that
bus->removedoes not get called on probe failure. Isn't that right?
Yep, I looked too fast.
Thanks,
Rusty.
Am Sunday 10 May 2009 06:07:06 schrieb Rusty Russell:
Quoted 3 lines
Yes, and in fact a rough look at your patch reveals that we don't actually need
del_vq: now we track them, we can just do that as part of vdev destruction, right?
Some of my students are working on a test module for virtio. Its a driver that matches all virtio IDs which can be used via bind/unbind. We currently use del_vq/find_vq in non device_release code. I will recheck but my feeling is that I want to keep del_vq.
Christian
Am Sunday 10 May 2009 06:07:06 schrieb Rusty Russell:
Quoted 3 lines
Yes, and in fact a rough look at your patch reveals that we don't actually need
del_vq: now we track them, we can just do that as part of vdev destruction, right?
Some of my students are working on a test module for virtio. Its a driver that matches all virtio IDs which can be used via bind/unbind. We currently use del_vq/find_vq in non device_release code. I will recheck but my feeling is that I want to keep del_vq.
Christian
Michael S. Tsirkin
maintainerPATCH 2/3 virtio_pci: split up vp_interrupt
In reply to a message not in the archiveThis reorganizes virtio-pci code in vp_interrupt slightly, so that it's easier to add per-vq MSI support on top.
--- drivers/virtio/virtio_pci.c | 45 +++++++++++++++++++++++++++++++++--------- 1 files changed, 35 insertions(+), 10 deletions(-)
drivers/virtio/virtio_pci.c +35 -10
@@ -164,6 +164,37 @@ static void vp_notify(struct virtqueue *vq)iowrite16 (info->queue_index, vp_dev->ioaddr +VIRTIO_PCI_QUEUE_NOTIFY ); } +/* Handle a configuration change: Tell driver if it wants to know. */ +static irqreturn_t vp_config_changed (int irq,void *opaque) +{ +struct virtio_pci_device *vp_dev = opaque; +struct virtio_driver *drv; + drv =container_of (vp_dev->vdev.dev.driver, + struct virtio_driver, driver); + +if (drv && drv->config_changed) + drv->config_changed (&vp_dev->vdev); +return IRQ_HANDLED ; +} + +/* Notify all virtqueues on an interrupt. */ +static irqreturn_t vp_vring_interrupt (int irq,void *opaque) +{ +struct virtio_pci_device *vp_dev = opaque; +struct virtio_pci_vq_info *info; +irqreturn_t ret =IRQ_NONE ; +unsigned long flags; + +spin_lock_irqsave (&vp_dev->lock, flags); +list_for_each_entry (info, &vp_dev->virtqueues, node) { +if (vring_interrupt (irq, info->vq) ==IRQ_HANDLED ) + ret =IRQ_HANDLED ; + } +spin_unlock_irqrestore (&vp_dev->lock, flags); + +return ret; +} +/* A small wrapper to also acknowledge the interrupt when it's handled. * I really need an EIO hook for the vring so I can ack the interrupt once we * know that we'll be handling the IRQ but before we invoke the callback since
@@ -173,9 +204,6 @@ static void vp_notify(struct virtqueue *vq)static irqreturn_t vp_interrupt (int irq,void *opaque) {struct virtio_pci_device *vp_dev = opaque; -struct virtio_pci_vq_info *info; -irqreturn_t ret =IRQ_NONE ; -unsigned long flags;u8 isr;/* reading the ISR has the effect of also clearing it so it's very
@@ -187,14 +215,11 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)return IRQ_NONE ;/* Configuration change? Tell driver if it wants to know. */ -if (isr &VIRTIO_PCI_ISR_CONFIG ) { -struct virtio_driver *drv; - drv =container_of (vp_dev->vdev.dev.driver, - struct virtio_driver, driver); +if (isr &VIRTIO_PCI_ISR_CONFIG ) +vp_config_changed (irq, opaque); -if (drv && drv->config_changed) - drv->config_changed (&vp_dev->vdev); - } +return vp_vring_interrupt (irq, opaque); +}spin_lock_irqsave (&vp_dev->lock, flags);list_for_each_entry (info, &vp_dev->virtqueues, node) {
Signature · 1 line
1.6.3.rc3.1.g830204
Michael S. Tsirkin
maintainerPATCH 2/3 virtio_pci: split up vp_interrupt
In reply to a message not in the archiveThis reorganizes virtio-pci code in vp_interrupt slightly, so that it's easier to add per-vq MSI support on top.
--- drivers/virtio/virtio_pci.c | 45 +++++++++++++++++++++++++++++++++--------- 1 files changed, 35 insertions(+), 10 deletions(-)
drivers/virtio/virtio_pci.c +35 -10
@@ -164,6 +164,37 @@ static void vp_notify(struct virtqueue *vq)iowrite16 (info->queue_index, vp_dev->ioaddr +VIRTIO_PCI_QUEUE_NOTIFY ); } +/* Handle a configuration change: Tell driver if it wants to know. */ +static irqreturn_t vp_config_changed (int irq,void *opaque) +{ +struct virtio_pci_device *vp_dev = opaque; +struct virtio_driver *drv; + drv =container_of (vp_dev->vdev.dev.driver, + struct virtio_driver, driver); + +if (drv && drv->config_changed) + drv->config_changed (&vp_dev->vdev); +return IRQ_HANDLED ; +} + +/* Notify all virtqueues on an interrupt. */ +static irqreturn_t vp_vring_interrupt (int irq,void *opaque) +{ +struct virtio_pci_device *vp_dev = opaque; +struct virtio_pci_vq_info *info; +irqreturn_t ret =IRQ_NONE ; +unsigned long flags; + +spin_lock_irqsave (&vp_dev->lock, flags); +list_for_each_entry (info, &vp_dev->virtqueues, node) { +if (vring_interrupt (irq, info->vq) ==IRQ_HANDLED ) + ret =IRQ_HANDLED ; + } +spin_unlock_irqrestore (&vp_dev->lock, flags); + +return ret; +} +/* A small wrapper to also acknowledge the interrupt when it's handled. * I really need an EIO hook for the vring so I can ack the interrupt once we * know that we'll be handling the IRQ but before we invoke the callback since
@@ -173,9 +204,6 @@ static void vp_notify(struct virtqueue *vq)static irqreturn_t vp_interrupt (int irq,void *opaque) {struct virtio_pci_device *vp_dev = opaque; -struct virtio_pci_vq_info *info; -irqreturn_t ret =IRQ_NONE ; -unsigned long flags;u8 isr;/* reading the ISR has the effect of also clearing it so it's very
@@ -187,14 +215,11 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)return IRQ_NONE ;/* Configuration change? Tell driver if it wants to know. */ -if (isr &VIRTIO_PCI_ISR_CONFIG ) { -struct virtio_driver *drv; - drv =container_of (vp_dev->vdev.dev.driver, - struct virtio_driver, driver); +if (isr &VIRTIO_PCI_ISR_CONFIG ) +vp_config_changed (irq, opaque); -if (drv && drv->config_changed) - drv->config_changed (&vp_dev->vdev); - } +return vp_vring_interrupt (irq, opaque); +}spin_lock_irqsave (&vp_dev->lock, flags);list_for_each_entry (info, &vp_dev->virtqueues, node) {
Signature · 1 line
1.6.3.rc3.1.g830204
Michael S. Tsirkin
maintainerPATCH 3/3 virtio_pci: optional MSI-X support
In reply to a message not in the archiveThis implements optional MSI-X support in virtio_pci. MSI-X is used whenever the host supports at least 2 MSI-X
vectors: 1 for configuration changes and 1 for virtqueues. Per-virtqueue vectors are allocated if enough vectors available.
--- drivers/virtio/virtio_pci.c | 209 +++++++++++++++++++++++++++++++++++++------ include/linux/virtio_pci.h | 8 ++- 2 files changed, 190 insertions(+), 27 deletions(-)
include/linux/virtio_pci.h +7 -1
@@ -47,9 +47,15 @@/* The bit of the ISR which indicates a device configuration change. */ #define VIRTIO_PCI_ISR_CONFIG 0x2 +/* MSI-X registers: only enabled if MSI-X is enabled. */ +/* A 16-bit vector for configuration changes. */ +#define VIRTIO_MSI_CONFIG_VECTOR 20 +/* A 16-bit vector for selected queue notifications. */ +#define VIRTIO_MSI_QUEUE_VECTOR 22 +/* The remaining space is defined by each driver as the per-driver * configuration space */ -#define VIRTIO_PCI_CONFIG 20 +#define VIRTIO_PCI_CONFIG (dev) ((dev)->msix_enabled ? 24 : 20)/* Virtio ABI version, this must match exactly */ #define VIRTIO_PCI_ABI_VERSION 0
drivers/virtio/virtio_pci.c +183 -26
314 lines not on this page · raw message
Signature · 1 line
1.6.3.rc3.1.g830204
Michael S. Tsirkin
maintainerPATCH 3/3 virtio_pci: optional MSI-X support
In reply to a message not in the archiveThis implements optional MSI-X support in virtio_pci. MSI-X is used whenever the host supports at least 2 MSI-X
vectors: 1 for configuration changes and 1 for virtqueues. Per-virtqueue vectors are allocated if enough vectors available.
--- drivers/virtio/virtio_pci.c | 209 +++++++++++++++++++++++++++++++++++++------ include/linux/virtio_pci.h | 8 ++- 2 files changed, 190 insertions(+), 27 deletions(-)
include/linux/virtio_pci.h +7 -1
@@ -47,9 +47,15 @@/* The bit of the ISR which indicates a device configuration change. */ #define VIRTIO_PCI_ISR_CONFIG 0x2 +/* MSI-X registers: only enabled if MSI-X is enabled. */ +/* A 16-bit vector for configuration changes. */ +#define VIRTIO_MSI_CONFIG_VECTOR 20 +/* A 16-bit vector for selected queue notifications. */ +#define VIRTIO_MSI_QUEUE_VECTOR 22 +/* The remaining space is defined by each driver as the per-driver * configuration space */ -#define VIRTIO_PCI_CONFIG 20 +#define VIRTIO_PCI_CONFIG (dev) ((dev)->msix_enabled ? 24 : 20)/* Virtio ABI version, this must match exactly */ #define VIRTIO_PCI_ABI_VERSION 0
drivers/virtio/virtio_pci.c +183 -26
314 lines not on this page · raw message
Signature · 1 line
1.6.3.rc3.1.g830204