aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/virtio_console.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/virtio_console.c')
-rw-r--r--drivers/char/virtio_console.c77
1 files changed, 33 insertions, 44 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 237eee26fbc3..7671914be172 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1048,7 +1048,7 @@ static void handle_control_message(struct ports_device *portdev,
1048 cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); 1048 cpkt = (struct virtio_console_control *)(buf->buf + buf->offset);
1049 1049
1050 port = find_port_by_id(portdev, cpkt->id); 1050 port = find_port_by_id(portdev, cpkt->id);
1051 if (!port) { 1051 if (!port && cpkt->event != VIRTIO_CONSOLE_PORT_ADD) {
1052 /* No valid header at start of buffer. Drop it. */ 1052 /* No valid header at start of buffer. Drop it. */
1053 dev_dbg(&portdev->vdev->dev, 1053 dev_dbg(&portdev->vdev->dev,
1054 "Invalid index %u in control packet\n", cpkt->id); 1054 "Invalid index %u in control packet\n", cpkt->id);
@@ -1056,6 +1056,30 @@ static void handle_control_message(struct ports_device *portdev,
1056 } 1056 }
1057 1057
1058 switch (cpkt->event) { 1058 switch (cpkt->event) {
1059 case VIRTIO_CONSOLE_PORT_ADD:
1060 if (port) {
1061 /*
1062 * This can happen for port 0: we have to
1063 * create a console port during probe() as was
1064 * the behaviour before the MULTIPORT feature.
1065 * On a newer host, when the host tells us
1066 * that a port 0 is available, we should just
1067 * say we have the port all set up.
1068 */
1069 send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
1070 break;
1071 }
1072 if (cpkt->id >= portdev->config.max_nr_ports) {
1073 dev_warn(&portdev->vdev->dev,
1074 "Request for adding port with out-of-bound id %u, max. supported id: %u\n",
1075 cpkt->id, portdev->config.max_nr_ports - 1);
1076 break;
1077 }
1078 add_port(portdev, cpkt->id);
1079 break;
1080 case VIRTIO_CONSOLE_PORT_REMOVE:
1081 remove_port(port);
1082 break;
1059 case VIRTIO_CONSOLE_CONSOLE_PORT: 1083 case VIRTIO_CONSOLE_CONSOLE_PORT:
1060 if (!cpkt->value) 1084 if (!cpkt->value)
1061 break; 1085 break;
@@ -1114,32 +1138,6 @@ static void handle_control_message(struct ports_device *portdev,
1114 kobject_uevent(&port->dev->kobj, KOBJ_CHANGE); 1138 kobject_uevent(&port->dev->kobj, KOBJ_CHANGE);
1115 } 1139 }
1116 break; 1140 break;
1117 case VIRTIO_CONSOLE_PORT_REMOVE:
1118 /*
1119 * Hot unplug the port. We don't decrement nr_ports
1120 * since we don't want to deal with extra complexities
1121 * of using the lowest-available port id: We can just
1122 * pick up the nr_ports number as the id and not have
1123 * userspace send it to us. This helps us in two
1124 * ways:
1125 *
1126 * - We don't need to have a 'port_id' field in the
1127 * config space when a port is hot-added. This is a
1128 * good thing as we might queue up multiple hotplug
1129 * requests issued in our workqueue.
1130 *
1131 * - Another way to deal with this would have been to
1132 * use a bitmap of the active ports and select the
1133 * lowest non-active port from that map. That
1134 * bloats the already tight config space and we
1135 * would end up artificially limiting the
1136 * max. number of ports to sizeof(bitmap). Right
1137 * now we can support 2^32 ports (as the port id is
1138 * stored in a u32 type).
1139 *
1140 */
1141 remove_port(port);
1142 break;
1143 } 1141 }
1144} 1142}
1145 1143
@@ -1347,7 +1345,6 @@ static const struct file_operations portdev_fops = {
1347static int __devinit virtcons_probe(struct virtio_device *vdev) 1345static int __devinit virtcons_probe(struct virtio_device *vdev)
1348{ 1346{
1349 struct ports_device *portdev; 1347 struct ports_device *portdev;
1350 u32 i;
1351 int err; 1348 int err;
1352 bool multiport; 1349 bool multiport;
1353 1350
@@ -1376,29 +1373,15 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
1376 } 1373 }
1377 1374
1378 multiport = false; 1375 multiport = false;
1379 portdev->config.nr_ports = 1;
1380 portdev->config.max_nr_ports = 1; 1376 portdev->config.max_nr_ports = 1;
1381 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { 1377 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
1382 multiport = true; 1378 multiport = true;
1383 vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; 1379 vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT;
1384 1380
1385 vdev->config->get(vdev, offsetof(struct virtio_console_config, 1381 vdev->config->get(vdev, offsetof(struct virtio_console_config,
1386 nr_ports),
1387 &portdev->config.nr_ports,
1388 sizeof(portdev->config.nr_ports));
1389 vdev->config->get(vdev, offsetof(struct virtio_console_config,
1390 max_nr_ports), 1382 max_nr_ports),
1391 &portdev->config.max_nr_ports, 1383 &portdev->config.max_nr_ports,
1392 sizeof(portdev->config.max_nr_ports)); 1384 sizeof(portdev->config.max_nr_ports));
1393 if (portdev->config.nr_ports > portdev->config.max_nr_ports) {
1394 dev_warn(&vdev->dev,
1395 "More ports (%u) specified than allowed (%u). Will init %u ports.",
1396 portdev->config.nr_ports,
1397 portdev->config.max_nr_ports,
1398 portdev->config.max_nr_ports);
1399
1400 portdev->config.nr_ports = portdev->config.max_nr_ports;
1401 }
1402 } 1385 }
1403 1386
1404 /* Let the Host know we support multiple ports.*/ 1387 /* Let the Host know we support multiple ports.*/
@@ -1428,11 +1411,17 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
1428 } 1411 }
1429 } 1412 }
1430 1413
1431 for (i = 0; i < portdev->config.nr_ports; i++) 1414 /*
1432 add_port(portdev, i); 1415 * For backward compatibility: if we're running on an older
1416 * host, we always want to create a console port.
1417 */
1418 add_port(portdev, 0);
1433 1419
1434 /* Start using the new console output. */ 1420 /* Start using the new console output. */
1435 early_put_chars = NULL; 1421 early_put_chars = NULL;
1422
1423 __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
1424 VIRTIO_CONSOLE_DEVICE_READY, 1);
1436 return 0; 1425 return 0;
1437 1426
1438free_vqs: 1427free_vqs: