diff options
| -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: |
