virtio: add names to virtqueue struct, mapping from devices to queues.
authorRusty Russell <rusty@rustcorp.com.au>
Sat, 13 Jun 2009 04:16:35 +0000 (22:16 -0600)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 12 Jun 2009 12:46:36 +0000 (22:16 +0930)
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 <rusty@rustcorp.com.au>
14 files changed:
drivers/block/virtio_blk.c
drivers/char/hw_random/virtio-rng.c
drivers/char/virtio_console.c
drivers/lguest/lguest_device.c
drivers/net/virtio_net.c
drivers/s390/kvm/kvm_virtio.c
drivers/virtio/virtio.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
include/linux/virtio.h
include/linux/virtio_config.h
include/linux/virtio_ring.h
net/9p/trans_virtio.c

index c0facaa55cf46ee96932d08ee453829735bdf939..db55a50d9f6ad73ee5fc1f795c1688fefb114bf3 100644 (file)
@@ -288,7 +288,7 @@ 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);
+       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;
index 86e83f883139e154d8f8621b2aa6650468ed74d8..2aeafcea95fe757982e8fdd4bc078ff9d7b5d6c3 100644 (file)
@@ -94,7 +94,7 @@ static int virtrng_probe(struct virtio_device *vdev)
        int 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);
 
index ff6f5a4b58fb5acd25622ad4fdd1b1a9c45b15f0..58684e4a0814453a1f6b6cb5576b411f124fb944 100644 (file)
@@ -202,13 +202,13 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
        /* 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;
index df44d962626d327ba26a3b1a2aa83a2bba383390..4babed899d5915e82a9cfeb2e01429afdabfcec0 100644 (file)
@@ -228,7 +228,8 @@ extern void lguest_setup_irq(unsigned int irq);
  * 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(struct virtio_device *vdev,
        /* 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;
index 4d1d47953fc6e4d780c538b5ffd00c901ffc06bf..be3b734ff5a12581e4a241d8b7ff166f57895875 100644 (file)
@@ -906,20 +906,20 @@ static int virtnet_probe(struct virtio_device *vdev)
                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;
index cbc8566fab705f954aae795f18ff58744b93b9c7..ba8995fbf041aa492a9104e9c65da32fd5184d5c 100644 (file)
@@ -173,8 +173,9 @@ static void kvm_notify(struct virtqueue *vq)
  * 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(struct virtio_device *vdev,
 
        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;
index 6b6810364860c858f62a778953b5e1399dfc6103..3f52c767dfe99f59b9861391d7d64a3f6b274764 100644 (file)
@@ -186,6 +186,8 @@ int register_virtio_device(struct virtio_device *dev)
        /* 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);
index 9c76a061a04dc7235ad689cea438fc8d0c6cfedf..0fa73b4d18b0f57e412cbe7581036bc16a31c2f3 100644 (file)
@@ -218,13 +218,13 @@ 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);
+       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;
index 330aacbdec1f7b48fd2774f19e5788461463f07a..be4047abd5ba9f2b8dcf9401de6a1337a4a91f28 100644 (file)
@@ -208,7 +208,8 @@ static irqreturn_t vp_interrupt(int irq, void *opaque)
 
 /* 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(struct virtio_device *vdev, unsigned index,
 
        /* 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;
index 5c52369ab9bb81115376ec3e8b959908bdbe8d8f..579fa693d5d0dbcb6400ed8994df0b49d4d8aea7 100644 (file)
 
 #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)
+       } 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(unsigned int num,
                                      struct 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(unsigned int num,
        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);
index 9410394bbf96917f95d89c45d963bcca61eb25d4..4fca4f5440ba47c93d7f903b8395a7b98791a021 100644 (file)
 
 /**
  * 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;
index bf8ec283b232af65116af4fa338ad602f1b8d798..9fae274751e0b0fb4e2a9b8b186a734cc574ed98 100644 (file)
@@ -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_ops
        void (*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);
index 71e03722fb5946fa60ab67a88a7250bee3c77b7c..166c519689dea8da43ad119dbf5bc010a6121311 100644 (file)
@@ -119,7 +119,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
                                      struct 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);
index bb8579a141a86c584db61993a86104316ba4cb43..ab8791f9aba822576112b17f8b4738463d42257e 100644 (file)
@@ -246,7 +246,7 @@ static int p9_virtio_probe(struct virtio_device *vdev)
        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;