diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2011-09-22 22:14:23 +0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2011-11-02 05:11:01 +0400 |
commit | 5e38483b350405542c8080134408fd8897394ba2 (patch) | |
tree | 34d746dadbec16fd33e4f08cf90561ee62a3014e /drivers/char | |
parent | 17e5b4f20adbe286fdf14b4d08f296564e97e545 (diff) | |
download | linux-5e38483b350405542c8080134408fd8897394ba2.tar.xz |
virtio: console: wait for first console port for early console output
On s390 I have seen some random
"Warning: unable to open an initial console"
boot failure. Turns out that tty_open fails, because the
hvc_alloc was not yet done. In former times this could not happen,
since the probe function automatically called hvc_alloc. With newer
versions (multiport) some host<->guest interaction is required
before hvc_alloc is called. This might be too late, especially if
an initramfs is involved. Lets use a completion if we have
multiport and an early console.
[Amit:
* Use NULL instead of 0 for pointer comparison
* Rename 'port_added' to 'early_console_added'
* Re-format, re-word commit message
* Rebase patch on top of current queue]
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Acked-by: Chrstian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/virtio_console.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 387fcdf019b7..4ca181f1378b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -19,6 +19,7 @@ */ #include <linux/cdev.h> #include <linux/debugfs.h> +#include <linux/completion.h> #include <linux/device.h> #include <linux/err.h> #include <linux/freezer.h> @@ -74,6 +75,7 @@ struct ports_driver_data { static struct ports_driver_data pdrvdata; DEFINE_SPINLOCK(pdrvdata_lock); +DECLARE_COMPLETION(early_console_added); /* This struct holds information that's relevant only for console ports */ struct console { @@ -1366,6 +1368,7 @@ static void handle_control_message(struct ports_device *portdev, break; init_port_console(port); + complete(&early_console_added); /* * Could remove the port here in case init fails - but * have to notify the host first. @@ -1668,6 +1671,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) struct ports_device *portdev; int err; bool multiport; + bool early = early_put_chars != NULL; + + /* Ensure to read early_put_chars now */ + barrier(); portdev = kmalloc(sizeof(*portdev), GFP_KERNEL); if (!portdev) { @@ -1737,6 +1744,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, VIRTIO_CONSOLE_DEVICE_READY, 1); + + /* + * If there was an early virtio console, assume that there are no + * other consoles. We need to wait until the hvc_alloc matches the + * hvc_instantiate, otherwise tty_open will complain, resulting in + * a "Warning: unable to open an initial console" boot failure. + * Without multiport this is done in add_port above. With multiport + * this might take some host<->guest communication - thus we have to + * wait. + */ + if (multiport && early) + wait_for_completion(&early_console_added); + return 0; free_vqs: |