void* vring_detach_unused_buf(struct virtqueue *_vq)
{
	struct vring_virtqueue *vq = to_vvq(_vq);
	unsigned int i;
	void *buf;

	for (i = 0; i < vq->vring.num; i++) {
		if (!vq->data[i])
			continue;
		buf = vq->data[i];
		detach_buf(vq, i);
		vq->vring.avail->idx--;
		return buf;
	}
	return NULL;
}
static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
{
	struct vring_virtqueue *vq = to_vvq(_vq);
	void *ret;
    struct vring_used_elem *u;
	unsigned int i;

	if (!more_used(vq)) {
		DPrintf(4, ("No more buffers in queue: last_used_idx %d vring.used->idx %d\n",
			vq->last_used_idx,
			vq->vring.used->idx));
		return NULL;
	}

	/* Only get used array entries after they have been exposed by host. */
	rmb();

	u = &vq->vring.used->ring[vq->last_used_idx % vq->vring.num];
	i = u->id;
	*len = u->len;


	DPrintf(4, ("%s>>> id %d, len %d\n", __FUNCTION__, i, *len) );

	if (i >= vq->vring.num) {
		DPrintf(0, ("id %u out of range\n", i) );
		return NULL;
	}
	if (!vq->data[i]) {
		DPrintf(0, ("id %u is not a head!\n", i) );
		return NULL;
	}

	/* detach_buf clears data, so grab it now. */
	ret = vq->data[i];
	detach_buf(vq, i);
	++vq->last_used_idx;

	if (!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
		*vq->vring.vring_last_used_ptr = vq->last_used_idx;
		mb();
	}

	return ret;
}
예제 #3
0
void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
{
	struct vring_virtqueue *vq = to_vvq(_vq);
	u16 last_used;
	unsigned i;
	void *ret;

	rmb();

	last_used = (vq->last_used_idx & (vq->vring.num-1));
	i = vq->vring.used->ring[last_used].id;
	*len = vq->vring.used->ring[last_used].len;

	ret = vq->data[i];
	detach_buf(vq, i);

	vq->last_used_idx++;

	return ret;
}
예제 #4
0
void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
{
	struct vring_virtqueue *vq = to_vvq(_vq);
	void *ret;
	unsigned int i;

	START_USE(vq);

	if (unlikely(vq->broken)) {
		END_USE(vq);
		return NULL;
	}

	if (!more_used(vq)) {
		pr_debug("No more buffers in queue\n");
		END_USE(vq);
		return NULL;
	}

	/* Only get used array entries after they have been exposed by host. */
	virtio_rmb();

	i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id;
	*len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len;

	if (unlikely(i >= vq->vring.num)) {
		BAD_RING(vq, "id %u out of range\n", i);
		return NULL;
	}
	if (unlikely(!vq->data[i])) {
		BAD_RING(vq, "id %u is not a head!\n", i);
		return NULL;
	}

	/* detach_buf clears data, so grab it now. */
	ret = vq->data[i];
	detach_buf(vq, i);
	vq->last_used_idx++;
	END_USE(vq);
	return ret;
}
예제 #5
0
void *virtqueue_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;
}