virtio-console: Only queue buffers we intend to read This may help with an outstanding issue where a Bluetooth device became unstable after a change to crosvm. It's possible that data from the host was being written into u-boot buffers and then being dropped. Bug: b/360926085 Test: launch_cvd --resume=false --bootloader=... Change-Id: I886f2fef150f213b41a7a317d22a89051294c36f
diff --git a/drivers/virtio/virtio_console.c b/drivers/virtio/virtio_console.c index b8c4512..9997159 100644 --- a/drivers/virtio/virtio_console.c +++ b/drivers/virtio/virtio_console.c
@@ -42,6 +42,7 @@ struct virtqueue *transmitq; int port_num; unsigned char char_inbuf[1] __aligned(sizeof(void *)); + bool buffer_queued; }; // Private data struct for the top-level virtio-console udevice. @@ -243,10 +244,6 @@ { int ret; - ret = add_char_inbuf(priv); - if (ret) - return log_msg_ret("Failed to set up initial character buffer", ret); - // QEMU will accept output on ports at any time, but will not pass // through input until it receives a VIRTIO_CONSOLE_PORT_OPEN on that // port number. It doesn't seem to produce a VIRTIO_CONSOLE_DEVICE_ADD @@ -281,6 +278,13 @@ if (ret) return ret; + if (!priv->buffer_queued) { + ret = add_char_inbuf(priv); + if (ret) + return log_msg_ret("Failed to set up character buffer", ret); + priv->buffer_queued = true; + } + in = virtqueue_get_buf(priv->receiveq, &len); if (!in) @@ -288,11 +292,9 @@ else if (len != 1) log_err("%s: too much data: %d\n", __func__, len); - int ch = *in; + priv->buffer_queued = false; - ret = add_char_inbuf(priv); - if (ret) - return log_msg_ret("Failed to set up character buffer", ret); + int ch = *in; return ch; } @@ -372,6 +374,7 @@ .receiveq = queues[(port_num * 2) + 2], .transmitq = queues[(port_num * 2) + 3], .port_num = port_num, + .buffer_queued = false, }; return log_ret(virtio_console_port_post_probe(priv)); @@ -405,10 +408,8 @@ .receiveq = virtqueues[0], .transmitq = virtqueues[1], .port_num = 0, + .buffer_queued = false, }; - ret = add_char_inbuf(&priv->port0); - if (ret) - return log_msg_ret("Failed to set up character buffer", ret); if (is_multiport == 0) { priv->receiveq_control = NULL;