diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-07 21:49:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-07 21:49:20 -0400 |
| commit | f5284e7635787224dda1a2bf82a4c56b1c75671f (patch) | |
| tree | 885730ccc2e890368e9012869e54538182fda8f7 | |
| parent | 3eac4abaa69949af0e2f64e5c55ee8a22bbdd3e7 (diff) | |
| parent | 320718ee074acce5ffced6506cb51af1388942aa (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
hvc_console: Fix race between hvc_close and hvc_remove
virtio: disable multiport console support.
virtio: console makes incorrect assumption about virtio API
virtio: console: Fix early_put_chars usage
MAINTAINERS: Put the virtio-console entry in correct alphabetical order
| -rw-r--r-- | MAINTAINERS | 13 | ||||
| -rw-r--r-- | drivers/char/hvc_console.c | 4 | ||||
| -rw-r--r-- | drivers/char/virtio_console.c | 65 | ||||
| -rw-r--r-- | include/linux/virtio_console.h | 23 |
4 files changed, 54 insertions, 51 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 3d29fa389888..7a9ccda2a307 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2474,12 +2474,6 @@ L: linuxppc-dev@ozlabs.org | |||
| 2474 | S: Odd Fixes | 2474 | S: Odd Fixes |
| 2475 | F: drivers/char/hvc_* | 2475 | F: drivers/char/hvc_* |
| 2476 | 2476 | ||
| 2477 | VIRTIO CONSOLE DRIVER | ||
| 2478 | M: Amit Shah <amit.shah@redhat.com> | ||
| 2479 | L: virtualization@lists.linux-foundation.org | ||
| 2480 | S: Maintained | ||
| 2481 | F: drivers/char/virtio_console.c | ||
| 2482 | |||
| 2483 | iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER | 2477 | iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER |
| 2484 | M: Peter Jones <pjones@redhat.com> | 2478 | M: Peter Jones <pjones@redhat.com> |
| 2485 | M: Konrad Rzeszutek Wilk <konrad@kernel.org> | 2479 | M: Konrad Rzeszutek Wilk <konrad@kernel.org> |
| @@ -5971,6 +5965,13 @@ S: Maintained | |||
| 5971 | F: Documentation/filesystems/vfat.txt | 5965 | F: Documentation/filesystems/vfat.txt |
| 5972 | F: fs/fat/ | 5966 | F: fs/fat/ |
| 5973 | 5967 | ||
| 5968 | VIRTIO CONSOLE DRIVER | ||
| 5969 | M: Amit Shah <amit.shah@redhat.com> | ||
| 5970 | L: virtualization@lists.linux-foundation.org | ||
| 5971 | S: Maintained | ||
| 5972 | F: drivers/char/virtio_console.c | ||
| 5973 | F: include/linux/virtio_console.h | ||
| 5974 | |||
| 5974 | VIRTIO HOST (VHOST) | 5975 | VIRTIO HOST (VHOST) |
| 5975 | M: "Michael S. Tsirkin" <mst@redhat.com> | 5976 | M: "Michael S. Tsirkin" <mst@redhat.com> |
| 5976 | L: kvm@vger.kernel.org | 5977 | L: kvm@vger.kernel.org |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index d3890e8d30e1..35cca4c7fb18 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
| @@ -368,16 +368,12 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
| 368 | hp = tty->driver_data; | 368 | hp = tty->driver_data; |
| 369 | 369 | ||
| 370 | spin_lock_irqsave(&hp->lock, flags); | 370 | spin_lock_irqsave(&hp->lock, flags); |
| 371 | tty_kref_get(tty); | ||
| 372 | 371 | ||
| 373 | if (--hp->count == 0) { | 372 | if (--hp->count == 0) { |
| 374 | /* We are done with the tty pointer now. */ | 373 | /* We are done with the tty pointer now. */ |
| 375 | hp->tty = NULL; | 374 | hp->tty = NULL; |
| 376 | spin_unlock_irqrestore(&hp->lock, flags); | 375 | spin_unlock_irqrestore(&hp->lock, flags); |
| 377 | 376 | ||
| 378 | /* Put the ref obtained in hvc_open() */ | ||
| 379 | tty_kref_put(tty); | ||
| 380 | |||
| 381 | if (hp->ops->notifier_del) | 377 | if (hp->ops->notifier_del) |
| 382 | hp->ops->notifier_del(hp, hp->data); | 378 | hp->ops->notifier_del(hp, hp->data); |
| 383 | 379 | ||
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 026ea6c27e07..196428c2287a 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -33,6 +33,35 @@ | |||
| 33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
| 34 | #include "hvc_console.h" | 34 | #include "hvc_console.h" |
| 35 | 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 | |||
| 39 | struct 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 | */ | ||
| 51 | struct 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 | |||
| 36 | /* | 65 | /* |
| 37 | * 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 |
| 38 | * this driver handles. | 67 | * this driver handles. |
| @@ -121,7 +150,7 @@ struct ports_device { | |||
| 121 | spinlock_t cvq_lock; | 150 | spinlock_t cvq_lock; |
| 122 | 151 | ||
| 123 | /* The current config space is stored here */ | 152 | /* The current config space is stored here */ |
| 124 | struct virtio_console_config config; | 153 | struct virtio_console_multiport_conf config; |
| 125 | 154 | ||
| 126 | /* The virtio device we're associated with */ | 155 | /* The virtio device we're associated with */ |
| 127 | struct virtio_device *vdev; | 156 | struct virtio_device *vdev; |
| @@ -416,20 +445,16 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count) | |||
| 416 | out_vq->vq_ops->kick(out_vq); | 445 | out_vq->vq_ops->kick(out_vq); |
| 417 | 446 | ||
| 418 | if (ret < 0) { | 447 | if (ret < 0) { |
| 419 | len = 0; | 448 | in_count = 0; |
| 420 | goto fail; | 449 | goto fail; |
| 421 | } | 450 | } |
| 422 | 451 | ||
| 423 | /* | 452 | /* Wait till the host acknowledges it pushed out the data we sent. */ |
| 424 | * Wait till the host acknowledges it pushed out the data we | ||
| 425 | * sent. Also ensure we return to userspace the number of | ||
| 426 | * bytes that were successfully consumed by the host. | ||
| 427 | */ | ||
| 428 | while (!out_vq->vq_ops->get_buf(out_vq, &len)) | 453 | while (!out_vq->vq_ops->get_buf(out_vq, &len)) |
| 429 | cpu_relax(); | 454 | cpu_relax(); |
| 430 | fail: | 455 | fail: |
| 431 | /* We're expected to return the amount of data we wrote */ | 456 | /* We're expected to return the amount of data we wrote */ |
| 432 | return len; | 457 | return in_count; |
| 433 | } | 458 | } |
| 434 | 459 | ||
| 435 | /* | 460 | /* |
| @@ -646,13 +671,13 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
| 646 | { | 671 | { |
| 647 | struct port *port; | 672 | struct port *port; |
| 648 | 673 | ||
| 674 | if (unlikely(early_put_chars)) | ||
| 675 | return early_put_chars(vtermno, buf, count); | ||
| 676 | |||
| 649 | port = find_port_by_vtermno(vtermno); | 677 | port = find_port_by_vtermno(vtermno); |
| 650 | if (!port) | 678 | if (!port) |
| 651 | return 0; | 679 | return 0; |
| 652 | 680 | ||
| 653 | if (unlikely(early_put_chars)) | ||
| 654 | return early_put_chars(vtermno, buf, count); | ||
| 655 | |||
| 656 | return send_buf(port, (void *)buf, count); | 681 | return send_buf(port, (void *)buf, count); |
| 657 | } | 682 | } |
| 658 | 683 | ||
| @@ -1218,7 +1243,7 @@ fail: | |||
| 1218 | */ | 1243 | */ |
| 1219 | static void config_work_handler(struct work_struct *work) | 1244 | static void config_work_handler(struct work_struct *work) |
| 1220 | { | 1245 | { |
| 1221 | struct virtio_console_config virtconconf; | 1246 | struct virtio_console_multiport_conf virtconconf; |
| 1222 | struct ports_device *portdev; | 1247 | struct ports_device *portdev; |
| 1223 | struct virtio_device *vdev; | 1248 | struct virtio_device *vdev; |
| 1224 | int err; | 1249 | int err; |
| @@ -1227,7 +1252,8 @@ static void config_work_handler(struct work_struct *work) | |||
| 1227 | 1252 | ||
| 1228 | vdev = portdev->vdev; | 1253 | vdev = portdev->vdev; |
| 1229 | vdev->config->get(vdev, | 1254 | vdev->config->get(vdev, |
| 1230 | offsetof(struct virtio_console_config, nr_ports), | 1255 | offsetof(struct virtio_console_multiport_conf, |
| 1256 | nr_ports), | ||
| 1231 | &virtconconf.nr_ports, | 1257 | &virtconconf.nr_ports, |
| 1232 | sizeof(virtconconf.nr_ports)); | 1258 | sizeof(virtconconf.nr_ports)); |
| 1233 | 1259 | ||
| @@ -1419,16 +1445,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
| 1419 | multiport = false; | 1445 | multiport = false; |
| 1420 | portdev->config.nr_ports = 1; | 1446 | portdev->config.nr_ports = 1; |
| 1421 | portdev->config.max_nr_ports = 1; | 1447 | portdev->config.max_nr_ports = 1; |
| 1448 | #if 0 /* Multiport is not quite ready yet --RR */ | ||
| 1422 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { | 1449 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { |
| 1423 | multiport = true; | 1450 | multiport = true; |
| 1424 | vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; | 1451 | vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; |
| 1425 | 1452 | ||
| 1426 | vdev->config->get(vdev, offsetof(struct virtio_console_config, | 1453 | vdev->config->get(vdev, |
| 1427 | nr_ports), | 1454 | offsetof(struct virtio_console_multiport_conf, |
| 1455 | nr_ports), | ||
| 1428 | &portdev->config.nr_ports, | 1456 | &portdev->config.nr_ports, |
| 1429 | sizeof(portdev->config.nr_ports)); | 1457 | sizeof(portdev->config.nr_ports)); |
| 1430 | vdev->config->get(vdev, offsetof(struct virtio_console_config, | 1458 | vdev->config->get(vdev, |
| 1431 | max_nr_ports), | 1459 | offsetof(struct virtio_console_multiport_conf, |
| 1460 | max_nr_ports), | ||
| 1432 | &portdev->config.max_nr_ports, | 1461 | &portdev->config.max_nr_ports, |
| 1433 | sizeof(portdev->config.max_nr_ports)); | 1462 | sizeof(portdev->config.max_nr_ports)); |
| 1434 | if (portdev->config.nr_ports > portdev->config.max_nr_ports) { | 1463 | if (portdev->config.nr_ports > portdev->config.max_nr_ports) { |
| @@ -1444,6 +1473,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
| 1444 | 1473 | ||
| 1445 | /* Let the Host know we support multiple ports.*/ | 1474 | /* Let the Host know we support multiple ports.*/ |
| 1446 | vdev->config->finalize_features(vdev); | 1475 | vdev->config->finalize_features(vdev); |
| 1476 | #endif | ||
| 1447 | 1477 | ||
| 1448 | err = init_vqs(portdev); | 1478 | err = init_vqs(portdev); |
| 1449 | if (err < 0) { | 1479 | if (err < 0) { |
| @@ -1526,7 +1556,6 @@ static struct virtio_device_id id_table[] = { | |||
| 1526 | 1556 | ||
| 1527 | static unsigned int features[] = { | 1557 | static unsigned int features[] = { |
| 1528 | VIRTIO_CONSOLE_F_SIZE, | 1558 | VIRTIO_CONSOLE_F_SIZE, |
| 1529 | VIRTIO_CONSOLE_F_MULTIPORT, | ||
| 1530 | }; | 1559 | }; |
| 1531 | 1560 | ||
| 1532 | static struct virtio_driver virtio_console = { | 1561 | static struct virtio_driver virtio_console = { |
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index ae4f039515b4..92228a8fbcbc 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h | |||
| @@ -12,37 +12,14 @@ | |||
| 12 | 12 | ||
| 13 | /* Feature bits */ | 13 | /* Feature bits */ |
| 14 | #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ | 14 | #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ |
| 15 | #define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ | ||
| 16 | 15 | ||
| 17 | struct virtio_console_config { | 16 | struct virtio_console_config { |
| 18 | /* colums of the screens */ | 17 | /* colums of the screens */ |
| 19 | __u16 cols; | 18 | __u16 cols; |
| 20 | /* rows of the screens */ | 19 | /* rows of the screens */ |
| 21 | __u16 rows; | 20 | __u16 rows; |
| 22 | /* max. number of ports this device can hold */ | ||
| 23 | __u32 max_nr_ports; | ||
| 24 | /* number of ports added so far */ | ||
| 25 | __u32 nr_ports; | ||
| 26 | } __attribute__((packed)); | 21 | } __attribute__((packed)); |
| 27 | 22 | ||
| 28 | /* | ||
| 29 | * A message that's passed between the Host and the Guest for a | ||
| 30 | * particular port. | ||
| 31 | */ | ||
| 32 | struct virtio_console_control { | ||
| 33 | __u32 id; /* Port number */ | ||
| 34 | __u16 event; /* The kind of control event (see below) */ | ||
| 35 | __u16 value; /* Extra information for the key */ | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* Some events for control messages */ | ||
| 39 | #define VIRTIO_CONSOLE_PORT_READY 0 | ||
| 40 | #define VIRTIO_CONSOLE_CONSOLE_PORT 1 | ||
| 41 | #define VIRTIO_CONSOLE_RESIZE 2 | ||
| 42 | #define VIRTIO_CONSOLE_PORT_OPEN 3 | ||
| 43 | #define VIRTIO_CONSOLE_PORT_NAME 4 | ||
| 44 | #define VIRTIO_CONSOLE_PORT_REMOVE 5 | ||
| 45 | |||
| 46 | #ifdef __KERNEL__ | 23 | #ifdef __KERNEL__ |
| 47 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); | 24 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); |
| 48 | #endif /* __KERNEL__ */ | 25 | #endif /* __KERNEL__ */ |
