|
@@ -334,6 +334,30 @@ static bool vring_enable_cb(struct virtqueue *_vq)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static void *vring_detach_unused_buf(struct virtqueue *_vq)
|
|
|
+{
|
|
|
+ struct vring_virtqueue *vq = to_vvq(_vq);
|
|
|
+ unsigned int i;
|
|
|
+ void *buf;
|
|
|
+
|
|
|
+ START_USE(vq);
|
|
|
+
|
|
|
+ for (i = 0; i < vq->vring.num; i++) {
|
|
|
+ if (!vq->data[i])
|
|
|
+ continue;
|
|
|
+ /* detach_buf clears data, so grab it now. */
|
|
|
+ buf = vq->data[i];
|
|
|
+ detach_buf(vq, i);
|
|
|
+ END_USE(vq);
|
|
|
+ return buf;
|
|
|
+ }
|
|
|
+ /* That should have freed everything. */
|
|
|
+ BUG_ON(vq->num_free != vq->vring.num);
|
|
|
+
|
|
|
+ END_USE(vq);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
irqreturn_t vring_interrupt(int irq, void *_vq)
|
|
|
{
|
|
|
struct vring_virtqueue *vq = to_vvq(_vq);
|
|
@@ -360,6 +384,7 @@ static struct virtqueue_ops vring_vq_ops = {
|
|
|
.kick = vring_kick,
|
|
|
.disable_cb = vring_disable_cb,
|
|
|
.enable_cb = vring_enable_cb,
|
|
|
+ .detach_unused_buf = vring_detach_unused_buf,
|
|
|
};
|
|
|
|
|
|
struct virtqueue *vring_new_virtqueue(unsigned int num,
|