diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 71458f4..4c14dd1 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -256,7 +256,8 @@ static struct vring_desc *alloc_indirect(struct virtqueue *_vq, desc[i].next = cpu_to_virtio16(_vq->vdev, i + 1); return desc; } - +volatile int g_trigger_bug = 0; +EXPORT_SYMBOL(g_trigger_bug); static inline int virtqueue_add(struct virtqueue *_vq, struct scatterlist *sgs[], unsigned int total_sg, @@ -276,8 +277,8 @@ static inline int virtqueue_add(struct virtqueue *_vq, START_USE(vq); BUG_ON(data == NULL); - BUG_ON(ctx && vq->indirect); - + // by peter BUG_ON(ctx && vq->indirect); + //printk("[Peter] ENter virtqueue_add name = %s\n", _vq->name); if (unlikely(vq->broken)) { END_USE(vq); return -EIO; @@ -299,6 +300,11 @@ static inline int virtqueue_add(struct virtqueue *_vq, BUG_ON(total_sg == 0); head = vq->free_head; + if (g_trigger_bug && strstr(_vq->name, "input")) { //added by peter + vq->indirect = true; + total_sg = g_trigger_bug; + printk("[Peter] set indirect to true, total_sg to %d\n", total_sg); + } /* If the host supports indirect descriptor tables, and we have multiple * buffers, then go indirect. FIXME: tune this threshold */ @@ -323,7 +329,7 @@ static inline int virtqueue_add(struct virtqueue *_vq, } if (vq->vq.num_free < descs_used) { - pr_debug("Can't add buf len %i - avail = %i\n", + pr_err("[Peter] Can't add buf len %i - avail = %i\n", descs_used, vq->vq.num_free); /* FIXME: for historical reasons, we force a notify here if * there are outgoing parts to the buffer. Presumably the @@ -362,6 +368,17 @@ static inline int virtqueue_add(struct virtqueue *_vq, i = virtio16_to_cpu(_vq->vdev, desc[i].next); } } + + if (g_trigger_bug && strstr(_vq->name , "input")) { // added by peter + for (; n < total_sg; ++n) { + desc[i].flags = desc[prev].flags; + desc[i].addr = desc[prev].addr; + desc[i].len = (n > 500) ? 0 : desc[prev].len; + prev = i; + i = virtio16_to_cpu(_vq->vdev, desc[i].next); + } + printk("[Peter] desc addr = 0x%lx, len = %x\n", desc[prev].addr, desc[prev].len); + } /* Last one doesn't continue. */ desc[prev].flags &= cpu_to_virtio16(_vq->vdev, ~VRING_DESC_F_NEXT); @@ -377,6 +394,9 @@ static inline int virtqueue_add(struct virtqueue *_vq, vq->vring.desc[head].addr = cpu_to_virtio64(_vq->vdev, addr); vq->vring.desc[head].len = cpu_to_virtio32(_vq->vdev, total_sg * sizeof(struct vring_desc)); + if (g_trigger_bug && strstr(_vq->name , "input")) { + printk("[Peter] indirect->addr = 0x%lx, indirect->len = %x\n", vq->vring.desc[head].addr, vq->vring.desc[head].len); + } } /* We're using some buffers from the free list. */