To identify which port data that gets sent to the Host belongs to, we'll have to add a 'header' to each outgoing buffer that will tell the Host the port number. This is also done for each buffer that's received from userspace. The header is currently a 0-length field, but will contain the port id among other things when support for multiple ports per device is added. Signed-off-by: Amit Shah <amit.shah@xxxxxxxxxx> --- drivers/char/virtio_console.c | 37 +++++++++++++++++++++++++++++++------ include/linux/virtio_console.h | 7 +++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 64a927c..def1678 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -150,24 +150,39 @@ out: return port; } +static inline bool use_multiport(struct ports_device *portdev) +{ + /* + * This condition can be true when put_chars is called from + * early_init + */ + if (!portdev->vdev) + return 0; + /* Check for feature bit once multiport support has been added */ + return 0; +} + static ssize_t send_buf(struct port *port, const char *in_buf, size_t in_count) { struct scatterlist sg[1]; + struct virtio_console_header header; struct virtqueue *out_vq; struct port_buffer *buf; size_t in_offset, copy_size; ssize_t ret; unsigned long irqf; + unsigned int header_len; if (!in_count) return 0; out_vq = port->portdev->out_vq; + header_len = use_multiport(port->portdev) ? sizeof(header) : 0; in_offset = 0; /* offset in the user buffer */ spin_lock_irqsave(&port->portdev->write_list_lock, irqf); while (in_count - in_offset) { - copy_size = min(in_count - in_offset, PAGE_SIZE); + copy_size = min(in_count - in_offset + header_len, PAGE_SIZE); if (list_empty(&port->portdev->unused_write_head)) break; @@ -177,15 +192,19 @@ static ssize_t send_buf(struct port *port, const char *in_buf, size_t in_count) list_del(&buf->list); spin_unlock_irqrestore(&port->portdev->write_list_lock, irqf); + if (header_len) { + memcpy(buf->buf, &header, header_len); + copy_size -= header_len; + } /* * Since we're not sure when the host will actually * consume the data and tell us about it, we have * to copy the data here in case the caller * frees the in_buf */ - memcpy(buf->buf, in_buf + in_offset, copy_size); + memcpy(buf->buf + header_len, in_buf + in_offset, copy_size); - buf->len = copy_size; + buf->len = header_len + copy_size; sg_init_one(sg, buf->buf, buf->len); spin_lock_irqsave(&port->portdev->write_list_lock, irqf); @@ -196,7 +215,7 @@ static ssize_t send_buf(struct port *port, const char *in_buf, size_t in_count) &port->portdev->unused_write_head); break; } - in_offset += buf->len; + in_offset += buf->len - header_len; /* No space left in the vq anyway */ if (!ret) @@ -494,19 +513,25 @@ static void *get_incoming_buf(struct ports_device *portdev, static void rx_work_handler(struct work_struct *work) { + struct virtio_console_header header; struct ports_device *portdev; struct port *port; struct port_buffer *buf; - unsigned int tmplen; + unsigned int tmplen, header_len; bool console_activity = false; portdev = container_of(work, struct ports_device, rx_work); + header_len = use_multiport(portdev) ? sizeof(header) : 0; /* We currently have only one port */ port = find_port_by_vtermno(0); while ((buf = get_incoming_buf(portdev, &tmplen))) { + + if (use_multiport(portdev)) + memcpy(&header, buf->buf, header_len); + buf->len = tmplen; - buf->offset = 0; + buf->offset = header_len; spin_lock_irq(&port->readbuf_list_lock); list_add_tail(&buf->list, &port->readbuf_head); diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index 9e0da40..3dfc7d1 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h @@ -18,6 +18,13 @@ struct virtio_console_config { __u16 rows; } __attribute__((packed)); +/* + * This struct is put at the start of each buffer that gets passed to + * Host and vice-versa. + */ +struct virtio_console_header { + /* Empty till multiport support is added */ +} __attribute__((packed)); #ifdef __KERNEL__ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); -- 1.6.2.5 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization