]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - Documentation/lguest/lguest.c
lguest: don't force VIRTIO_F_NOTIFY_ON_EMPTY
[net-next-2.6.git] / Documentation / lguest / lguest.c
index 84bbb190bf7ba440d31e01b685b0076db4ab5edd..ba9373f82ab5fa9fe62276cc27333447a22475ba 100644 (file)
@@ -134,6 +134,9 @@ struct device {
        /* Is it operational */
        bool running;
 
+       /* Does Guest want an intrrupt on empty? */
+       bool irq_on_empty;
+
        /* Device-specific data. */
        void *priv;
 };
@@ -624,10 +627,13 @@ static void trigger_irq(struct virtqueue *vq)
                return;
        vq->pending_used = 0;
 
-       /* If they don't want an interrupt, don't send one, unless empty. */
-       if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
-           && lg_last_avail(vq) != vq->vring.avail->idx)
-               return;
+       /* If they don't want an interrupt, don't send one... */
+       if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) {
+               /* ... unless they've asked us to force one on empty. */
+               if (!vq->dev->irq_on_empty
+                   || lg_last_avail(vq) != vq->vring.avail->idx)
+                       return;
+       }
 
        /* Send the Guest an interrupt tell them we used something up. */
        if (write(lguest_fd, buf, sizeof(buf)) != 0)
@@ -1043,6 +1049,15 @@ static void create_thread(struct virtqueue *vq)
        close(vq->eventfd);
 }
 
+static bool accepted_feature(struct device *dev, unsigned int bit)
+{
+       const u8 *features = get_feature_bits(dev) + dev->feature_len;
+
+       if (dev->feature_len < bit / CHAR_BIT)
+               return false;
+       return features[bit / CHAR_BIT] & (1 << (bit % CHAR_BIT));
+}
+
 static void start_device(struct device *dev)
 {
        unsigned int i;
@@ -1056,6 +1071,8 @@ static void start_device(struct device *dev)
                verbose(" %02x", get_feature_bits(dev)
                        [dev->feature_len+i]);
 
+       dev->irq_on_empty = accepted_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
+
        for (vq = dev->vq; vq; vq = vq->next) {
                if (vq->service)
                        create_thread(vq);