Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d6933561 authored by Amit Shah's avatar Amit Shah Committed by Rusty Russell
Browse files

virtio: console: Fill ports' entire in_vq with buffers



Instead of allocating just one buffer for a port's in_vq, fill
the entire in_vq with buffers so the host need not stall while
an application consumes the data and makes the buffer available
again for the host.

Signed-off-by: default avatarAmit Shah <amit.shah@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 22a29eac
Loading
Loading
Loading
Loading
+32 −21
Original line number Diff line number Diff line
@@ -330,6 +330,7 @@ static void discard_port_data(struct port *port)
	struct port_buffer *buf;
	struct virtqueue *vq;
	unsigned int len;
	int ret;

	vq = port->in_vq;
	if (port->inbuf)
@@ -337,16 +338,18 @@ static void discard_port_data(struct port *port)
	else
		buf = vq->vq_ops->get_buf(vq, &len);

	if (!buf)
		return;

	ret = 0;
	while (buf) {
		if (add_inbuf(vq, buf) < 0) {
		buf->len = buf->offset = 0;
		dev_warn(port->dev, "Error adding buffer back to vq\n");
		return;
			ret++;
			free_buf(buf);
		}
		buf = vq->vq_ops->get_buf(vq, &len);
	}

	port->inbuf = NULL;
	if (ret)
		dev_warn(port->dev, "Errors adding %d buffers back to vq\n",
			 ret);
}

static bool port_has_data(struct port *port)
@@ -354,12 +357,19 @@ static bool port_has_data(struct port *port)
	unsigned long flags;
	bool ret;

	ret = false;
	spin_lock_irqsave(&port->inbuf_lock, flags);
	if (port->inbuf)
	if (port->inbuf) {
		ret = true;
		goto out;
	}
	port->inbuf = get_inbuf(port);
	if (port->inbuf) {
		ret = true;
		goto out;
	}
	ret = false;
out:
	spin_unlock_irqrestore(&port->inbuf_lock, flags);

	return ret;
}

@@ -1011,6 +1021,7 @@ static void in_intr(struct virtqueue *vq)
		return;

	spin_lock_irqsave(&port->inbuf_lock, flags);
	if (!port->inbuf)
		port->inbuf = get_inbuf(port);

	/*
@@ -1087,7 +1098,7 @@ static int add_port(struct ports_device *portdev, u32 id)
{
	char debugfs_name[16];
	struct port *port;
	struct port_buffer *inbuf;
	struct port_buffer *buf;
	dev_t devt;
	int err;

@@ -1132,22 +1143,21 @@ static int add_port(struct ports_device *portdev, u32 id)
	spin_lock_init(&port->inbuf_lock);
	init_waitqueue_head(&port->waitqueue);

	inbuf = alloc_buf(PAGE_SIZE);
	if (!inbuf) {
	/* Fill the in_vq with buffers so the host can send us data. */
	err = fill_queue(port->in_vq, &port->inbuf_lock);
	if (!err) {
		dev_err(port->dev, "Error allocating inbufs\n");
		err = -ENOMEM;
		goto free_device;
	}

	/* Register the input buffer the first time. */
	add_inbuf(port->in_vq, inbuf);

	/*
	 * If we're not using multiport support, this has to be a console port
	 */
	if (!use_multiport(port->portdev)) {
		err = init_port_console(port);
		if (err)
			goto free_inbuf;
			goto free_inbufs;
	}

	spin_lock_irq(&portdev->ports_lock);
@@ -1175,8 +1185,9 @@ static int add_port(struct ports_device *portdev, u32 id)
	}
	return 0;

free_inbuf:
	free_buf(inbuf);
free_inbufs:
	while ((buf = port->in_vq->vq_ops->detach_unused_buf(port->in_vq)))
		free_buf(buf);
free_device:
	device_destroy(pdrvdata.class, port->dev->devt);
free_cdev: