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.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 44288ce0cb45..196428c2287a 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -25,6 +25,7 @@
25#include <linux/list.h> 25#include <linux/list.h>
26#include <linux/poll.h> 26#include <linux/poll.h>
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/slab.h>
28#include <linux/spinlock.h> 29#include <linux/spinlock.h>
29#include <linux/virtio.h> 30#include <linux/virtio.h>
30#include <linux/virtio_console.h> 31#include <linux/virtio_console.h>
@@ -32,6 +33,35 @@
32#include <linux/workqueue.h> 33#include <linux/workqueue.h>
33#include "hvc_console.h" 34#include "hvc_console.h"
34 35
36/* Moved here from .h file in order to disable MULTIPORT. */
37#define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */
38
39struct virtio_console_multiport_conf {
40 struct virtio_console_config config;
41 /* max. number of ports this device can hold */
42 __u32 max_nr_ports;
43 /* number of ports added so far */
44 __u32 nr_ports;
45} __attribute__((packed));
46
47/*
48 * A message that's passed between the Host and the Guest for a
49 * particular port.
50 */
51struct virtio_console_control {
52 __u32 id; /* Port number */
53 __u16 event; /* The kind of control event (see below) */
54 __u16 value; /* Extra information for the key */
55};
56
57/* Some events for control messages */
58#define VIRTIO_CONSOLE_PORT_READY 0
59#define VIRTIO_CONSOLE_CONSOLE_PORT 1
60#define VIRTIO_CONSOLE_RESIZE 2
61#define VIRTIO_CONSOLE_PORT_OPEN 3
62#define VIRTIO_CONSOLE_PORT_NAME 4
63#define VIRTIO_CONSOLE_PORT_REMOVE 5
64
35/* 65/*
36 * This is a global struct for storing common data for all the devices 66 * This is a global struct for storing common data for all the devices
37 * this driver handles. 67 * this driver handles.
@@ -120,7 +150,7 @@ struct ports_device {
120 spinlock_t cvq_lock; 150 spinlock_t cvq_lock;
121 151
122 /* The current config space is stored here */ 152 /* The current config space is stored here */
123 struct virtio_console_config config; 153 struct virtio_console_multiport_conf config;
124 154
125 /* The virtio device we're associated with */ 155 /* The virtio device we're associated with */
126 struct virtio_device *vdev; 156 struct virtio_device *vdev;
@@ -415,20 +445,16 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count)
415 out_vq->vq_ops->kick(out_vq); 445 out_vq->vq_ops->kick(out_vq);
416 446
417 if (ret < 0) { 447 if (ret < 0) {
418 len = 0; 448 in_count = 0;
419 goto fail; 449 goto fail;
420 } 450 }
421 451
422 /* 452 /* Wait till the host acknowledges it pushed out the data we sent. */
423 * Wait till the host acknowledges it pushed out the data we
424 * sent. Also ensure we return to userspace the number of
425 * bytes that were successfully consumed by the host.
426 */
427 while (!out_vq->vq_ops->get_buf(out_vq, &len)) 453 while (!out_vq->vq_ops->get_buf(out_vq, &len))
428 cpu_relax(); 454 cpu_relax();
429fail: 455fail:
430 /* We're expected to return the amount of data we wrote */ 456 /* We're expected to return the amount of data we wrote */
431 return len; 457 return in_count;
432} 458}
433 459
434/* 460/*
@@ -645,13 +671,13 @@ static int put_chars(u32 vtermno, const char *buf, int count)
645{ 671{
646 struct port *port; 672 struct port *port;
647 673
674 if (unlikely(early_put_chars))
675 return early_put_chars(vtermno, buf, count);
676
648 port = find_port_by_vtermno(vtermno); 677 port = find_port_by_vtermno(vtermno);
649 if (!port) 678 if (!port)
650 return 0; 679 return 0;
651 680
652 if (unlikely(early_put_chars))
653 return early_put_chars(vtermno, buf, count);
654
655 return send_buf(port, (void *)buf, count); 681 return send_buf(port, (void *)buf, count);
656} 682}
657 683
@@ -1217,7 +1243,7 @@ fail:
1217 */ 1243 */
1218static void config_work_handler(struct work_struct *work) 1244static void config_work_handler(struct work_struct *work)
1219{ 1245{
1220 struct virtio_console_config virtconconf; 1246 struct virtio_console_multiport_conf virtconconf;
1221 struct ports_device *portdev; 1247 struct ports_device *portdev;
1222 struct virtio_device *vdev; 1248 struct virtio_device *vdev;
1223 int err; 1249 int err;
@@ -1226,7 +1252,8 @@ static void config_work_handler(struct work_struct *work)
1226 1252
1227 vdev = portdev->vdev; 1253 vdev = portdev->vdev;
1228 vdev->config->get(vdev, 1254 vdev->config->get(vdev,
1229 offsetof(struct virtio_console_config, nr_ports), 1255 offsetof(struct virtio_console_multiport_conf,
1256 nr_ports),
1230 &virtconconf.nr_ports, 1257 &virtconconf.nr_ports,
1231 sizeof(virtconconf.nr_ports)); 1258 sizeof(virtconconf.nr_ports));
1232 1259
@@ -1418,16 +1445,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
1418 multiport = false; 1445 multiport = false;
1419 portdev->config.nr_ports = 1; 1446 portdev->config.nr_ports = 1;
1420 portdev->config.max_nr_ports = 1; 1447 portdev->config.max_nr_ports = 1;
1448#if 0 /* Multiport is not quite ready yet --RR */
1421 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { 1449 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
1422 multiport = true; 1450 multiport = true;
1423 vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; 1451 vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT;
1424 1452
1425 vdev->config->get(vdev, offsetof(struct virtio_console_config, 1453 vdev->config->get(vdev,
1426 nr_ports), 1454 offsetof(struct virtio_console_multiport_conf,
1455 nr_ports),
1427 &portdev->config.nr_ports, 1456 &portdev->config.nr_ports,
1428 sizeof(portdev->config.nr_ports)); 1457 sizeof(portdev->config.nr_ports));
1429 vdev->config->get(vdev, offsetof(struct virtio_console_config, 1458 vdev->config->get(vdev,
1430 max_nr_ports), 1459 offsetof(struct virtio_console_multiport_conf,
1460 max_nr_ports),
1431 &portdev->config.max_nr_ports, 1461 &portdev->config.max_nr_ports,
1432 sizeof(portdev->config.max_nr_ports)); 1462 sizeof(portdev->config.max_nr_ports));
1433 if (portdev->config.nr_ports > portdev->config.max_nr_ports) { 1463 if (portdev->config.nr_ports > portdev->config.max_nr_ports) {
@@ -1443,6 +1473,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
1443 1473
1444 /* Let the Host know we support multiple ports.*/ 1474 /* Let the Host know we support multiple ports.*/
1445 vdev->config->finalize_features(vdev); 1475 vdev->config->finalize_features(vdev);
1476#endif
1446 1477
1447 err = init_vqs(portdev); 1478 err = init_vqs(portdev);
1448 if (err < 0) { 1479 if (err < 0) {
@@ -1525,7 +1556,6 @@ static struct virtio_device_id id_table[] = {
1525 1556
1526static unsigned int features[] = { 1557static unsigned int features[] = {
1527 VIRTIO_CONSOLE_F_SIZE, 1558 VIRTIO_CONSOLE_F_SIZE,
1528 VIRTIO_CONSOLE_F_MULTIPORT,
1529}; 1559};
1530 1560
1531static struct virtio_driver virtio_console = { 1561static struct virtio_driver virtio_console = {