diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2011-09-22 14:14:23 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2011-11-01 21:11:01 -0400 |
commit | 5e38483b350405542c8080134408fd8897394ba2 (patch) | |
tree | 34d746dadbec16fd33e4f08cf90561ee62a3014e /drivers/char | |
parent | 17e5b4f20adbe286fdf14b4d08f296564e97e545 (diff) |
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 @@ | |||
19 | */ | 19 | */ |
20 | #include <linux/cdev.h> | 20 | #include <linux/cdev.h> |
21 | #include <linux/debugfs.h> | 21 | #include <linux/debugfs.h> |
22 | #include <linux/completion.h> | ||
22 | #include <linux/device.h> | 23 | #include <linux/device.h> |
23 | #include <linux/err.h> | 24 | #include <linux/err.h> |
24 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
@@ -74,6 +75,7 @@ struct ports_driver_data { | |||
74 | static struct ports_driver_data pdrvdata; | 75 | static struct ports_driver_data pdrvdata; |
75 | 76 | ||
76 | DEFINE_SPINLOCK(pdrvdata_lock); | 77 | DEFINE_SPINLOCK(pdrvdata_lock); |
78 | DECLARE_COMPLETION(early_console_added); | ||
77 | 79 | ||
78 | /* This struct holds information that's relevant only for console ports */ | 80 | /* This struct holds information that's relevant only for console ports */ |
79 | struct console { | 81 | struct console { |
@@ -1366,6 +1368,7 @@ static void handle_control_message(struct ports_device *portdev, | |||
1366 | break; | 1368 | break; |
1367 | 1369 | ||
1368 | init_port_console(port); | 1370 | init_port_console(port); |
1371 | complete(&early_console_added); | ||
1369 | /* | 1372 | /* |
1370 | * Could remove the port here in case init fails - but | 1373 | * Could remove the port here in case init fails - but |
1371 | * have to notify the host first. | 1374 | * have to notify the host first. |
@@ -1668,6 +1671,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1668 | struct ports_device *portdev; | 1671 | struct ports_device *portdev; |
1669 | int err; | 1672 | int err; |
1670 | bool multiport; | 1673 | bool multiport; |
1674 | bool early = early_put_chars != NULL; | ||
1675 | |||
1676 | /* Ensure to read early_put_chars now */ | ||
1677 | barrier(); | ||
1671 | 1678 | ||
1672 | portdev = kmalloc(sizeof(*portdev), GFP_KERNEL); | 1679 | portdev = kmalloc(sizeof(*portdev), GFP_KERNEL); |
1673 | if (!portdev) { | 1680 | if (!portdev) { |
@@ -1737,6 +1744,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1737 | 1744 | ||
1738 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | 1745 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
1739 | VIRTIO_CONSOLE_DEVICE_READY, 1); | 1746 | VIRTIO_CONSOLE_DEVICE_READY, 1); |
1747 | |||
1748 | /* | ||
1749 | * If there was an early virtio console, assume that there are no | ||
1750 | * other consoles. We need to wait until the hvc_alloc matches the | ||
1751 | * hvc_instantiate, otherwise tty_open will complain, resulting in | ||
1752 | * a "Warning: unable to open an initial console" boot failure. | ||
1753 | * Without multiport this is done in add_port above. With multiport | ||
1754 | * this might take some host<->guest communication - thus we have to | ||
1755 | * wait. | ||
1756 | */ | ||
1757 | if (multiport && early) | ||
1758 | wait_for_completion(&early_console_added); | ||
1759 | |||
1740 | return 0; | 1760 | return 0; |
1741 | 1761 | ||
1742 | free_vqs: | 1762 | free_vqs: |