aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2011-09-22 14:14:23 -0400
committerRusty Russell <rusty@rustcorp.com.au>2011-11-01 21:11:01 -0400
commit5e38483b350405542c8080134408fd8897394ba2 (patch)
tree34d746dadbec16fd33e4f08cf90561ee62a3014e /drivers/char
parent17e5b4f20adbe286fdf14b4d08f296564e97e545 (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.c20
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 {
74static struct ports_driver_data pdrvdata; 75static struct ports_driver_data pdrvdata;
75 76
76DEFINE_SPINLOCK(pdrvdata_lock); 77DEFINE_SPINLOCK(pdrvdata_lock);
78DECLARE_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 */
79struct console { 81struct 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
1742free_vqs: 1762free_vqs: