Keep a list of all ports being used as a console, and provide a lock and a lookup function. The hvc callbacks only give us a vterm number, so we need to map this.
Signed-off-by: Rusty Russell <[email protected]> --- drivers/char/virtio_console.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -28,16 +28,45 @@ struct port { char *inbuf; unsigned int used_len, offset; + /* For console ports, hvc != NULL and these are valid. */ /* The hvc device */ struct hvc_struct *hvc; + + /* ports_by_vtermno */ + struct list_head vtermno_list; + + /* Our vterm number. */ + u32 vtermno; }; +/* The list of ports. */ +static LIST_HEAD(ports_by_vtermno); + +/* The lock on the port list. */ +static DEFINE_SPINLOCK(ports_by_vtermno_lock); + /* We have one port ready to go immediately, for a console. */ static struct port console; /* This is the very early put chars function. */ static int (*early_put_chars)(u32, const char *, int); +static struct port *find_port_by_vtermno(u32 vtermno) +{ + unsigned long flags; + struct port *port; + + spin_lock_irqsave(&ports_by_vtermno_lock, flags); + list_for_each_entry(port, &ports_by_vtermno, vtermno_list) { + if (port->hvc && port->vtermno == vtermno) + goto out; + } + port = NULL; +out: + spin_unlock_irqrestore(&ports_by_vtermno_lock, flags); + return port; +} + /* The put_chars() callback is pretty straightforward. * * We turn the characters into a scatter-gather list, add it to the output @@ -48,7 +77,7 @@ static int put_chars(u32 vtermno, const { struct scatterlist sg[1]; unsigned int len; - struct port *port = &console; + struct port *port = find_port_by_vtermno(vtermno); if (unlikely(early_put_chars)) return early_put_chars(vtermno, buf, count); @@ -89,7 +118,7 @@ static void add_inbuf(struct port *port) * for partially-filled buffers. */ static int get_chars(u32 vtermno, char *buf, int count) { - struct port *port = &console; + struct port *port = find_port_by_vtermno(vtermno); /* If we don't have an input queue yet, we can't get input. */ BUG_ON(!port->in_vq); @@ -137,13 +166,13 @@ static void virtcons_apply_config(struct } /* - * we support only one console, the hvc struct is a global var * We set the configuration at this point, since we now have a tty */ static int notifier_add_vio(struct hvc_struct *hp, int data) { + struct port *port = find_port_by_vtermno(hp->vtermno); hp->irq_requested = 1; - virtcons_apply_config(console.vdev); + virtcons_apply_config(port->vdev); return 0; } @@ -232,6 +261,11 @@ static int __devinit virtcons_probe(stru goto free_vqs; } + /* Add to vtermno list. */ + spin_lock_irq(&ports_by_vtermno_lock); + list_add(&port->vtermno_list, &ports_by_vtermno); + spin_unlock_irq(&ports_by_vtermno_lock); + /* Register the input buffer the first time. */ add_inbuf(port); _______________________________________________ Virtualization mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/virtualization
