aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 20:22:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 20:22:52 -0400
commit1756ac3d3c41341297ea25b818b7fce505bb2a9a (patch)
tree96382220afbb82fd5c576c4c08b3c3e13282851f /drivers/char
parent98edb6ca4174f17a64890a02f44c211c8b44fb3c (diff)
parent0643e4c6e4fd67778fa886a89e6ec2320e0ff4d3 (diff)
Merge branch 'virtio' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* 'virtio' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: (27 commits) drivers/char: Eliminate use after free virtio: console: Accept console size along with resize control message virtio: console: Store each console's size in the console structure virtio: console: Resize console port 0 on config intr only if multiport is off virtio: console: Add support for nonblocking write()s virtio: console: Rename wait_is_over() to will_read_block() virtio: console: Don't always create a port 0 if using multiport virtio: console: Use a control message to add ports virtio: console: Move code around for future patches virtio: console: Remove config work handler virtio: console: Don't call hvc_remove() on unplugging console ports virtio: console: Return -EPIPE to hvc_console if we lost the connection virtio: console: Let host know of port or device add failures virtio: console: Add a __send_control_msg() that can send messages without a valid port virtio: Revert "virtio: disable multiport console support." virtio: add_buf_gfp trans_virtio: use virtqueue_xxx wrappers virtio-rng: use virtqueue_xxx wrappers virtio_ring: remove a level of indirection virtio_net: use virtqueue_xxx wrappers ... Fix up conflicts in drivers/net/virtio_net.c due to new virtqueue_xxx wrappers changes conflicting with some other cleanups.
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hw_random/virtio-rng.c6
-rw-r--r--drivers/char/virtio_console.c700
2 files changed, 380 insertions, 326 deletions
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 64fe0a793efd..75f1cbd61c17 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -32,7 +32,7 @@ static bool busy;
32static void random_recv_done(struct virtqueue *vq) 32static void random_recv_done(struct virtqueue *vq)
33{ 33{
34 /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ 34 /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
35 if (!vq->vq_ops->get_buf(vq, &data_avail)) 35 if (!virtqueue_get_buf(vq, &data_avail))
36 return; 36 return;
37 37
38 complete(&have_data); 38 complete(&have_data);
@@ -46,10 +46,10 @@ static void register_buffer(u8 *buf, size_t size)
46 sg_init_one(&sg, buf, size); 46 sg_init_one(&sg, buf, size);
47 47
48 /* There should always be room for one buffer. */ 48 /* There should always be room for one buffer. */
49 if (vq->vq_ops->add_buf(vq, &sg, 0, 1, buf) < 0) 49 if (virtqueue_add_buf(vq, &sg, 0, 1, buf) < 0)
50 BUG(); 50 BUG();
51 51
52 vq->vq_ops->kick(vq); 52 virtqueue_kick(vq);
53} 53}
54 54
55static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) 55static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 196428c2287a..8c99bf1b5e9f 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -33,35 +33,6 @@
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
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
65/* 36/*
66 * This is a global struct for storing common data for all the devices 37 * This is a global struct for storing common data for all the devices
67 * this driver handles. 38 * this driver handles.
@@ -107,6 +78,9 @@ struct console {
107 /* The hvc device associated with this console port */ 78 /* The hvc device associated with this console port */
108 struct hvc_struct *hvc; 79 struct hvc_struct *hvc;
109 80
81 /* The size of the console */
82 struct winsize ws;
83
110 /* 84 /*
111 * This number identifies the number that we used to register 85 * This number identifies the number that we used to register
112 * with hvc in hvc_instantiate() and hvc_alloc(); this is the 86 * with hvc in hvc_instantiate() and hvc_alloc(); this is the
@@ -139,7 +113,6 @@ struct ports_device {
139 * notification 113 * notification
140 */ 114 */
141 struct work_struct control_work; 115 struct work_struct control_work;
142 struct work_struct config_work;
143 116
144 struct list_head ports; 117 struct list_head ports;
145 118
@@ -150,7 +123,7 @@ struct ports_device {
150 spinlock_t cvq_lock; 123 spinlock_t cvq_lock;
151 124
152 /* The current config space is stored here */ 125 /* The current config space is stored here */
153 struct virtio_console_multiport_conf config; 126 struct virtio_console_config config;
154 127
155 /* The virtio device we're associated with */ 128 /* The virtio device we're associated with */
156 struct virtio_device *vdev; 129 struct virtio_device *vdev;
@@ -189,6 +162,9 @@ struct port {
189 */ 162 */
190 spinlock_t inbuf_lock; 163 spinlock_t inbuf_lock;
191 164
165 /* Protect the operations on the out_vq. */
166 spinlock_t outvq_lock;
167
192 /* The IO vqs for this port */ 168 /* The IO vqs for this port */
193 struct virtqueue *in_vq, *out_vq; 169 struct virtqueue *in_vq, *out_vq;
194 170
@@ -214,6 +190,8 @@ struct port {
214 /* The 'id' to identify the port with the Host */ 190 /* The 'id' to identify the port with the Host */
215 u32 id; 191 u32 id;
216 192
193 bool outvq_full;
194
217 /* Is the host device open */ 195 /* Is the host device open */
218 bool host_connected; 196 bool host_connected;
219 197
@@ -328,7 +306,7 @@ static void *get_inbuf(struct port *port)
328 unsigned int len; 306 unsigned int len;
329 307
330 vq = port->in_vq; 308 vq = port->in_vq;
331 buf = vq->vq_ops->get_buf(vq, &len); 309 buf = virtqueue_get_buf(vq, &len);
332 if (buf) { 310 if (buf) {
333 buf->len = len; 311 buf->len = len;
334 buf->offset = 0; 312 buf->offset = 0;
@@ -349,8 +327,8 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf)
349 327
350 sg_init_one(sg, buf->buf, buf->size); 328 sg_init_one(sg, buf->buf, buf->size);
351 329
352 ret = vq->vq_ops->add_buf(vq, sg, 0, 1, buf); 330 ret = virtqueue_add_buf(vq, sg, 0, 1, buf);
353 vq->vq_ops->kick(vq); 331 virtqueue_kick(vq);
354 return ret; 332 return ret;
355} 333}
356 334
@@ -366,7 +344,7 @@ static void discard_port_data(struct port *port)
366 if (port->inbuf) 344 if (port->inbuf)
367 buf = port->inbuf; 345 buf = port->inbuf;
368 else 346 else
369 buf = vq->vq_ops->get_buf(vq, &len); 347 buf = virtqueue_get_buf(vq, &len);
370 348
371 ret = 0; 349 ret = 0;
372 while (buf) { 350 while (buf) {
@@ -374,7 +352,7 @@ static void discard_port_data(struct port *port)
374 ret++; 352 ret++;
375 free_buf(buf); 353 free_buf(buf);
376 } 354 }
377 buf = vq->vq_ops->get_buf(vq, &len); 355 buf = virtqueue_get_buf(vq, &len);
378 } 356 }
379 port->inbuf = NULL; 357 port->inbuf = NULL;
380 if (ret) 358 if (ret)
@@ -403,57 +381,96 @@ out:
403 return ret; 381 return ret;
404} 382}
405 383
406static ssize_t send_control_msg(struct port *port, unsigned int event, 384static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
407 unsigned int value) 385 unsigned int event, unsigned int value)
408{ 386{
409 struct scatterlist sg[1]; 387 struct scatterlist sg[1];
410 struct virtio_console_control cpkt; 388 struct virtio_console_control cpkt;
411 struct virtqueue *vq; 389 struct virtqueue *vq;
412 unsigned int len; 390 unsigned int len;
413 391
414 if (!use_multiport(port->portdev)) 392 if (!use_multiport(portdev))
415 return 0; 393 return 0;
416 394
417 cpkt.id = port->id; 395 cpkt.id = port_id;
418 cpkt.event = event; 396 cpkt.event = event;
419 cpkt.value = value; 397 cpkt.value = value;
420 398
421 vq = port->portdev->c_ovq; 399 vq = portdev->c_ovq;
422 400
423 sg_init_one(sg, &cpkt, sizeof(cpkt)); 401 sg_init_one(sg, &cpkt, sizeof(cpkt));
424 if (vq->vq_ops->add_buf(vq, sg, 1, 0, &cpkt) >= 0) { 402 if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt) >= 0) {
425 vq->vq_ops->kick(vq); 403 virtqueue_kick(vq);
426 while (!vq->vq_ops->get_buf(vq, &len)) 404 while (!virtqueue_get_buf(vq, &len))
427 cpu_relax(); 405 cpu_relax();
428 } 406 }
429 return 0; 407 return 0;
430} 408}
431 409
432static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count) 410static ssize_t send_control_msg(struct port *port, unsigned int event,
411 unsigned int value)
412{
413 return __send_control_msg(port->portdev, port->id, event, value);
414}
415
416/* Callers must take the port->outvq_lock */
417static void reclaim_consumed_buffers(struct port *port)
418{
419 void *buf;
420 unsigned int len;
421
422 while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
423 kfree(buf);
424 port->outvq_full = false;
425 }
426}
427
428static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
429 bool nonblock)
433{ 430{
434 struct scatterlist sg[1]; 431 struct scatterlist sg[1];
435 struct virtqueue *out_vq; 432 struct virtqueue *out_vq;
436 ssize_t ret; 433 ssize_t ret;
434 unsigned long flags;
437 unsigned int len; 435 unsigned int len;
438 436
439 out_vq = port->out_vq; 437 out_vq = port->out_vq;
440 438
439 spin_lock_irqsave(&port->outvq_lock, flags);
440
441 reclaim_consumed_buffers(port);
442
441 sg_init_one(sg, in_buf, in_count); 443 sg_init_one(sg, in_buf, in_count);
442 ret = out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, in_buf); 444 ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf);
443 445
444 /* Tell Host to go! */ 446 /* Tell Host to go! */
445 out_vq->vq_ops->kick(out_vq); 447 virtqueue_kick(out_vq);
446 448
447 if (ret < 0) { 449 if (ret < 0) {
448 in_count = 0; 450 in_count = 0;
449 goto fail; 451 goto done;
450 } 452 }
451 453
452 /* Wait till the host acknowledges it pushed out the data we sent. */ 454 if (ret == 0)
453 while (!out_vq->vq_ops->get_buf(out_vq, &len)) 455 port->outvq_full = true;
456
457 if (nonblock)
458 goto done;
459
460 /*
461 * Wait till the host acknowledges it pushed out the data we
462 * sent. This is done for ports in blocking mode or for data
463 * from the hvc_console; the tty operations are performed with
464 * spinlocks held so we can't sleep here.
465 */
466 while (!virtqueue_get_buf(out_vq, &len))
454 cpu_relax(); 467 cpu_relax();
455fail: 468done:
456 /* We're expected to return the amount of data we wrote */ 469 spin_unlock_irqrestore(&port->outvq_lock, flags);
470 /*
471 * We're expected to return the amount of data we wrote -- all
472 * of it
473 */
457 return in_count; 474 return in_count;
458} 475}
459 476
@@ -503,9 +520,28 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count,
503} 520}
504 521
505/* The condition that must be true for polling to end */ 522/* The condition that must be true for polling to end */
506static bool wait_is_over(struct port *port) 523static bool will_read_block(struct port *port)
524{
525 return !port_has_data(port) && port->host_connected;
526}
527
528static bool will_write_block(struct port *port)
507{ 529{
508 return port_has_data(port) || !port->host_connected; 530 bool ret;
531
532 if (!port->host_connected)
533 return true;
534
535 spin_lock_irq(&port->outvq_lock);
536 /*
537 * Check if the Host has consumed any buffers since we last
538 * sent data (this is only applicable for nonblocking ports).
539 */
540 reclaim_consumed_buffers(port);
541 ret = port->outvq_full;
542 spin_unlock_irq(&port->outvq_lock);
543
544 return ret;
509} 545}
510 546
511static ssize_t port_fops_read(struct file *filp, char __user *ubuf, 547static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
@@ -528,7 +564,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
528 return -EAGAIN; 564 return -EAGAIN;
529 565
530 ret = wait_event_interruptible(port->waitqueue, 566 ret = wait_event_interruptible(port->waitqueue,
531 wait_is_over(port)); 567 !will_read_block(port));
532 if (ret < 0) 568 if (ret < 0)
533 return ret; 569 return ret;
534 } 570 }
@@ -554,9 +590,22 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
554 struct port *port; 590 struct port *port;
555 char *buf; 591 char *buf;
556 ssize_t ret; 592 ssize_t ret;
593 bool nonblock;
557 594
558 port = filp->private_data; 595 port = filp->private_data;
559 596
597 nonblock = filp->f_flags & O_NONBLOCK;
598
599 if (will_write_block(port)) {
600 if (nonblock)
601 return -EAGAIN;
602
603 ret = wait_event_interruptible(port->waitqueue,
604 !will_write_block(port));
605 if (ret < 0)
606 return ret;
607 }
608
560 count = min((size_t)(32 * 1024), count); 609 count = min((size_t)(32 * 1024), count);
561 610
562 buf = kmalloc(count, GFP_KERNEL); 611 buf = kmalloc(count, GFP_KERNEL);
@@ -569,9 +618,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
569 goto free_buf; 618 goto free_buf;
570 } 619 }
571 620
572 ret = send_buf(port, buf, count); 621 ret = send_buf(port, buf, count, nonblock);
622
623 if (nonblock && ret > 0)
624 goto out;
625
573free_buf: 626free_buf:
574 kfree(buf); 627 kfree(buf);
628out:
575 return ret; 629 return ret;
576} 630}
577 631
@@ -586,7 +640,7 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
586 ret = 0; 640 ret = 0;
587 if (port->inbuf) 641 if (port->inbuf)
588 ret |= POLLIN | POLLRDNORM; 642 ret |= POLLIN | POLLRDNORM;
589 if (port->host_connected) 643 if (!will_write_block(port))
590 ret |= POLLOUT; 644 ret |= POLLOUT;
591 if (!port->host_connected) 645 if (!port->host_connected)
592 ret |= POLLHUP; 646 ret |= POLLHUP;
@@ -610,6 +664,10 @@ static int port_fops_release(struct inode *inode, struct file *filp)
610 664
611 spin_unlock_irq(&port->inbuf_lock); 665 spin_unlock_irq(&port->inbuf_lock);
612 666
667 spin_lock_irq(&port->outvq_lock);
668 reclaim_consumed_buffers(port);
669 spin_unlock_irq(&port->outvq_lock);
670
613 return 0; 671 return 0;
614} 672}
615 673
@@ -638,6 +696,15 @@ static int port_fops_open(struct inode *inode, struct file *filp)
638 port->guest_connected = true; 696 port->guest_connected = true;
639 spin_unlock_irq(&port->inbuf_lock); 697 spin_unlock_irq(&port->inbuf_lock);
640 698
699 spin_lock_irq(&port->outvq_lock);
700 /*
701 * There might be a chance that we missed reclaiming a few
702 * buffers in the window of the port getting previously closed
703 * and opening now.
704 */
705 reclaim_consumed_buffers(port);
706 spin_unlock_irq(&port->outvq_lock);
707
641 /* Notify host of port being opened */ 708 /* Notify host of port being opened */
642 send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); 709 send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1);
643 710
@@ -676,9 +743,9 @@ static int put_chars(u32 vtermno, const char *buf, int count)
676 743
677 port = find_port_by_vtermno(vtermno); 744 port = find_port_by_vtermno(vtermno);
678 if (!port) 745 if (!port)
679 return 0; 746 return -EPIPE;
680 747
681 return send_buf(port, (void *)buf, count); 748 return send_buf(port, (void *)buf, count, false);
682} 749}
683 750
684/* 751/*
@@ -692,9 +759,13 @@ static int get_chars(u32 vtermno, char *buf, int count)
692{ 759{
693 struct port *port; 760 struct port *port;
694 761
762 /* If we've not set up the port yet, we have no input to give. */
763 if (unlikely(early_put_chars))
764 return 0;
765
695 port = find_port_by_vtermno(vtermno); 766 port = find_port_by_vtermno(vtermno);
696 if (!port) 767 if (!port)
697 return 0; 768 return -EPIPE;
698 769
699 /* If we don't have an input queue yet, we can't get input. */ 770 /* If we don't have an input queue yet, we can't get input. */
700 BUG_ON(!port->in_vq); 771 BUG_ON(!port->in_vq);
@@ -705,22 +776,14 @@ static int get_chars(u32 vtermno, char *buf, int count)
705static void resize_console(struct port *port) 776static void resize_console(struct port *port)
706{ 777{
707 struct virtio_device *vdev; 778 struct virtio_device *vdev;
708 struct winsize ws;
709 779
710 /* The port could have been hot-unplugged */ 780 /* The port could have been hot-unplugged */
711 if (!port) 781 if (!port || !is_console_port(port))
712 return; 782 return;
713 783
714 vdev = port->portdev->vdev; 784 vdev = port->portdev->vdev;
715 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) { 785 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE))
716 vdev->config->get(vdev, 786 hvc_resize(port->cons.hvc, port->cons.ws);
717 offsetof(struct virtio_console_config, cols),
718 &ws.ws_col, sizeof(u16));
719 vdev->config->get(vdev,
720 offsetof(struct virtio_console_config, rows),
721 &ws.ws_row, sizeof(u16));
722 hvc_resize(port->cons.hvc, ws);
723 }
724} 787}
725 788
726/* We set the configuration at this point, since we now have a tty */ 789/* We set the configuration at this point, since we now have a tty */
@@ -804,6 +867,13 @@ int init_port_console(struct port *port)
804 spin_unlock_irq(&pdrvdata_lock); 867 spin_unlock_irq(&pdrvdata_lock);
805 port->guest_connected = true; 868 port->guest_connected = true;
806 869
870 /*
871 * Start using the new console output if this is the first
872 * console to come up.
873 */
874 if (early_put_chars)
875 early_put_chars = NULL;
876
807 /* Notify host of port being opened */ 877 /* Notify host of port being opened */
808 send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); 878 send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
809 879
@@ -859,6 +929,8 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf,
859 out_offset += snprintf(buf + out_offset, out_count - out_offset, 929 out_offset += snprintf(buf + out_offset, out_count - out_offset,
860 "host_connected: %d\n", port->host_connected); 930 "host_connected: %d\n", port->host_connected);
861 out_offset += snprintf(buf + out_offset, out_count - out_offset, 931 out_offset += snprintf(buf + out_offset, out_count - out_offset,
932 "outvq_full: %d\n", port->outvq_full);
933 out_offset += snprintf(buf + out_offset, out_count - out_offset,
862 "is_console: %s\n", 934 "is_console: %s\n",
863 is_console_port(port) ? "yes" : "no"); 935 is_console_port(port) ? "yes" : "no");
864 out_offset += snprintf(buf + out_offset, out_count - out_offset, 936 out_offset += snprintf(buf + out_offset, out_count - out_offset,
@@ -875,6 +947,153 @@ static const struct file_operations port_debugfs_ops = {
875 .read = debugfs_read, 947 .read = debugfs_read,
876}; 948};
877 949
950static void set_console_size(struct port *port, u16 rows, u16 cols)
951{
952 if (!port || !is_console_port(port))
953 return;
954
955 port->cons.ws.ws_row = rows;
956 port->cons.ws.ws_col = cols;
957}
958
959static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
960{
961 struct port_buffer *buf;
962 unsigned int nr_added_bufs;
963 int ret;
964
965 nr_added_bufs = 0;
966 do {
967 buf = alloc_buf(PAGE_SIZE);
968 if (!buf)
969 break;
970
971 spin_lock_irq(lock);
972 ret = add_inbuf(vq, buf);
973 if (ret < 0) {
974 spin_unlock_irq(lock);
975 free_buf(buf);
976 break;
977 }
978 nr_added_bufs++;
979 spin_unlock_irq(lock);
980 } while (ret > 0);
981
982 return nr_added_bufs;
983}
984
985static int add_port(struct ports_device *portdev, u32 id)
986{
987 char debugfs_name[16];
988 struct port *port;
989 struct port_buffer *buf;
990 dev_t devt;
991 unsigned int nr_added_bufs;
992 int err;
993
994 port = kmalloc(sizeof(*port), GFP_KERNEL);
995 if (!port) {
996 err = -ENOMEM;
997 goto fail;
998 }
999
1000 port->portdev = portdev;
1001 port->id = id;
1002
1003 port->name = NULL;
1004 port->inbuf = NULL;
1005 port->cons.hvc = NULL;
1006
1007 port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
1008
1009 port->host_connected = port->guest_connected = false;
1010
1011 port->outvq_full = false;
1012
1013 port->in_vq = portdev->in_vqs[port->id];
1014 port->out_vq = portdev->out_vqs[port->id];
1015
1016 cdev_init(&port->cdev, &port_fops);
1017
1018 devt = MKDEV(portdev->chr_major, id);
1019 err = cdev_add(&port->cdev, devt, 1);
1020 if (err < 0) {
1021 dev_err(&port->portdev->vdev->dev,
1022 "Error %d adding cdev for port %u\n", err, id);
1023 goto free_port;
1024 }
1025 port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
1026 devt, port, "vport%up%u",
1027 port->portdev->drv_index, id);
1028 if (IS_ERR(port->dev)) {
1029 err = PTR_ERR(port->dev);
1030 dev_err(&port->portdev->vdev->dev,
1031 "Error %d creating device for port %u\n",
1032 err, id);
1033 goto free_cdev;
1034 }
1035
1036 spin_lock_init(&port->inbuf_lock);
1037 spin_lock_init(&port->outvq_lock);
1038 init_waitqueue_head(&port->waitqueue);
1039
1040 /* Fill the in_vq with buffers so the host can send us data. */
1041 nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
1042 if (!nr_added_bufs) {
1043 dev_err(port->dev, "Error allocating inbufs\n");
1044 err = -ENOMEM;
1045 goto free_device;
1046 }
1047
1048 /*
1049 * If we're not using multiport support, this has to be a console port
1050 */
1051 if (!use_multiport(port->portdev)) {
1052 err = init_port_console(port);
1053 if (err)
1054 goto free_inbufs;
1055 }
1056
1057 spin_lock_irq(&portdev->ports_lock);
1058 list_add_tail(&port->list, &port->portdev->ports);
1059 spin_unlock_irq(&portdev->ports_lock);
1060
1061 /*
1062 * Tell the Host we're set so that it can send us various
1063 * configuration parameters for this port (eg, port name,
1064 * caching, whether this is a console port, etc.)
1065 */
1066 send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
1067
1068 if (pdrvdata.debugfs_dir) {
1069 /*
1070 * Finally, create the debugfs file that we can use to
1071 * inspect a port's state at any time
1072 */
1073 sprintf(debugfs_name, "vport%up%u",
1074 port->portdev->drv_index, id);
1075 port->debugfs_file = debugfs_create_file(debugfs_name, 0444,
1076 pdrvdata.debugfs_dir,
1077 port,
1078 &port_debugfs_ops);
1079 }
1080 return 0;
1081
1082free_inbufs:
1083 while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
1084 free_buf(buf);
1085free_device:
1086 device_destroy(pdrvdata.class, port->dev->devt);
1087free_cdev:
1088 cdev_del(&port->cdev);
1089free_port:
1090 kfree(port);
1091fail:
1092 /* The host might want to notify management sw about port add failure */
1093 __send_control_msg(portdev, id, VIRTIO_CONSOLE_PORT_READY, 0);
1094 return err;
1095}
1096
878/* Remove all port-specific data. */ 1097/* Remove all port-specific data. */
879static int remove_port(struct port *port) 1098static int remove_port(struct port *port)
880{ 1099{
@@ -888,7 +1107,18 @@ static int remove_port(struct port *port)
888 spin_lock_irq(&pdrvdata_lock); 1107 spin_lock_irq(&pdrvdata_lock);
889 list_del(&port->cons.list); 1108 list_del(&port->cons.list);
890 spin_unlock_irq(&pdrvdata_lock); 1109 spin_unlock_irq(&pdrvdata_lock);
1110#if 0
1111 /*
1112 * hvc_remove() not called as removing one hvc port
1113 * results in other hvc ports getting frozen.
1114 *
1115 * Once this is resolved in hvc, this functionality
1116 * will be enabled. Till that is done, the -EPIPE
1117 * return from get_chars() above will help
1118 * hvc_console.c to clean up on ports we remove here.
1119 */
891 hvc_remove(port->cons.hvc); 1120 hvc_remove(port->cons.hvc);
1121#endif
892 } 1122 }
893 if (port->guest_connected) 1123 if (port->guest_connected)
894 send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); 1124 send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
@@ -900,8 +1130,10 @@ static int remove_port(struct port *port)
900 /* Remove unused data this port might have received. */ 1130 /* Remove unused data this port might have received. */
901 discard_port_data(port); 1131 discard_port_data(port);
902 1132
1133 reclaim_consumed_buffers(port);
1134
903 /* Remove buffers we queued up for the Host to send us data in. */ 1135 /* Remove buffers we queued up for the Host to send us data in. */
904 while ((buf = port->in_vq->vq_ops->detach_unused_buf(port->in_vq))) 1136 while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
905 free_buf(buf); 1137 free_buf(buf);
906 1138
907 kfree(port->name); 1139 kfree(port->name);
@@ -924,7 +1156,7 @@ static void handle_control_message(struct ports_device *portdev,
924 cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); 1156 cpkt = (struct virtio_console_control *)(buf->buf + buf->offset);
925 1157
926 port = find_port_by_id(portdev, cpkt->id); 1158 port = find_port_by_id(portdev, cpkt->id);
927 if (!port) { 1159 if (!port && cpkt->event != VIRTIO_CONSOLE_PORT_ADD) {
928 /* No valid header at start of buffer. Drop it. */ 1160 /* No valid header at start of buffer. Drop it. */
929 dev_dbg(&portdev->vdev->dev, 1161 dev_dbg(&portdev->vdev->dev,
930 "Invalid index %u in control packet\n", cpkt->id); 1162 "Invalid index %u in control packet\n", cpkt->id);
@@ -932,6 +1164,24 @@ static void handle_control_message(struct ports_device *portdev,
932 } 1164 }
933 1165
934 switch (cpkt->event) { 1166 switch (cpkt->event) {
1167 case VIRTIO_CONSOLE_PORT_ADD:
1168 if (port) {
1169 dev_dbg(&portdev->vdev->dev,
1170 "Port %u already added\n", port->id);
1171 send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
1172 break;
1173 }
1174 if (cpkt->id >= portdev->config.max_nr_ports) {
1175 dev_warn(&portdev->vdev->dev,
1176 "Request for adding port with out-of-bound id %u, max. supported id: %u\n",
1177 cpkt->id, portdev->config.max_nr_ports - 1);
1178 break;
1179 }
1180 add_port(portdev, cpkt->id);
1181 break;
1182 case VIRTIO_CONSOLE_PORT_REMOVE:
1183 remove_port(port);
1184 break;
935 case VIRTIO_CONSOLE_CONSOLE_PORT: 1185 case VIRTIO_CONSOLE_CONSOLE_PORT:
936 if (!cpkt->value) 1186 if (!cpkt->value)
937 break; 1187 break;
@@ -944,15 +1194,34 @@ static void handle_control_message(struct ports_device *portdev,
944 * have to notify the host first. 1194 * have to notify the host first.
945 */ 1195 */
946 break; 1196 break;
947 case VIRTIO_CONSOLE_RESIZE: 1197 case VIRTIO_CONSOLE_RESIZE: {
1198 struct {
1199 __u16 rows;
1200 __u16 cols;
1201 } size;
1202
948 if (!is_console_port(port)) 1203 if (!is_console_port(port))
949 break; 1204 break;
1205
1206 memcpy(&size, buf->buf + buf->offset + sizeof(*cpkt),
1207 sizeof(size));
1208 set_console_size(port, size.rows, size.cols);
1209
950 port->cons.hvc->irq_requested = 1; 1210 port->cons.hvc->irq_requested = 1;
951 resize_console(port); 1211 resize_console(port);
952 break; 1212 break;
1213 }
953 case VIRTIO_CONSOLE_PORT_OPEN: 1214 case VIRTIO_CONSOLE_PORT_OPEN:
954 port->host_connected = cpkt->value; 1215 port->host_connected = cpkt->value;
955 wake_up_interruptible(&port->waitqueue); 1216 wake_up_interruptible(&port->waitqueue);
1217 /*
1218 * If the host port got closed and the host had any
1219 * unconsumed buffers, we'll be able to reclaim them
1220 * now.
1221 */
1222 spin_lock_irq(&port->outvq_lock);
1223 reclaim_consumed_buffers(port);
1224 spin_unlock_irq(&port->outvq_lock);
956 break; 1225 break;
957 case VIRTIO_CONSOLE_PORT_NAME: 1226 case VIRTIO_CONSOLE_PORT_NAME:
958 /* 1227 /*
@@ -990,32 +1259,6 @@ static void handle_control_message(struct ports_device *portdev,
990 kobject_uevent(&port->dev->kobj, KOBJ_CHANGE); 1259 kobject_uevent(&port->dev->kobj, KOBJ_CHANGE);
991 } 1260 }
992 break; 1261 break;
993 case VIRTIO_CONSOLE_PORT_REMOVE:
994 /*
995 * Hot unplug the port. We don't decrement nr_ports
996 * since we don't want to deal with extra complexities
997 * of using the lowest-available port id: We can just
998 * pick up the nr_ports number as the id and not have
999 * userspace send it to us. This helps us in two
1000 * ways:
1001 *
1002 * - We don't need to have a 'port_id' field in the
1003 * config space when a port is hot-added. This is a
1004 * good thing as we might queue up multiple hotplug
1005 * requests issued in our workqueue.
1006 *
1007 * - Another way to deal with this would have been to
1008 * use a bitmap of the active ports and select the
1009 * lowest non-active port from that map. That
1010 * bloats the already tight config space and we
1011 * would end up artificially limiting the
1012 * max. number of ports to sizeof(bitmap). Right
1013 * now we can support 2^32 ports (as the port id is
1014 * stored in a u32 type).
1015 *
1016 */
1017 remove_port(port);
1018 break;
1019 } 1262 }
1020} 1263}
1021 1264
@@ -1030,7 +1273,7 @@ static void control_work_handler(struct work_struct *work)
1030 vq = portdev->c_ivq; 1273 vq = portdev->c_ivq;
1031 1274
1032 spin_lock(&portdev->cvq_lock); 1275 spin_lock(&portdev->cvq_lock);
1033 while ((buf = vq->vq_ops->get_buf(vq, &len))) { 1276 while ((buf = virtqueue_get_buf(vq, &len))) {
1034 spin_unlock(&portdev->cvq_lock); 1277 spin_unlock(&portdev->cvq_lock);
1035 1278
1036 buf->len = len; 1279 buf->len = len;
@@ -1092,204 +1335,29 @@ static void config_intr(struct virtio_device *vdev)
1092 struct ports_device *portdev; 1335 struct ports_device *portdev;
1093 1336
1094 portdev = vdev->priv; 1337 portdev = vdev->priv;
1095 if (use_multiport(portdev)) {
1096 /* Handle port hot-add */
1097 schedule_work(&portdev->config_work);
1098 }
1099 /*
1100 * We'll use this way of resizing only for legacy support.
1101 * For newer userspace (VIRTIO_CONSOLE_F_MULTPORT+), use
1102 * control messages to indicate console size changes so that
1103 * it can be done per-port
1104 */
1105 resize_console(find_port_by_id(portdev, 0));
1106}
1107
1108static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
1109{
1110 struct port_buffer *buf;
1111 unsigned int nr_added_bufs;
1112 int ret;
1113
1114 nr_added_bufs = 0;
1115 do {
1116 buf = alloc_buf(PAGE_SIZE);
1117 if (!buf)
1118 break;
1119
1120 spin_lock_irq(lock);
1121 ret = add_inbuf(vq, buf);
1122 if (ret < 0) {
1123 spin_unlock_irq(lock);
1124 free_buf(buf);
1125 break;
1126 }
1127 nr_added_bufs++;
1128 spin_unlock_irq(lock);
1129 } while (ret > 0);
1130
1131 return nr_added_bufs;
1132}
1133
1134static int add_port(struct ports_device *portdev, u32 id)
1135{
1136 char debugfs_name[16];
1137 struct port *port;
1138 struct port_buffer *buf;
1139 dev_t devt;
1140 unsigned int nr_added_bufs;
1141 int err;
1142
1143 port = kmalloc(sizeof(*port), GFP_KERNEL);
1144 if (!port) {
1145 err = -ENOMEM;
1146 goto fail;
1147 }
1148
1149 port->portdev = portdev;
1150 port->id = id;
1151
1152 port->name = NULL;
1153 port->inbuf = NULL;
1154 port->cons.hvc = NULL;
1155
1156 port->host_connected = port->guest_connected = false;
1157
1158 port->in_vq = portdev->in_vqs[port->id];
1159 port->out_vq = portdev->out_vqs[port->id];
1160
1161 cdev_init(&port->cdev, &port_fops);
1162
1163 devt = MKDEV(portdev->chr_major, id);
1164 err = cdev_add(&port->cdev, devt, 1);
1165 if (err < 0) {
1166 dev_err(&port->portdev->vdev->dev,
1167 "Error %d adding cdev for port %u\n", err, id);
1168 goto free_port;
1169 }
1170 port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
1171 devt, port, "vport%up%u",
1172 port->portdev->drv_index, id);
1173 if (IS_ERR(port->dev)) {
1174 err = PTR_ERR(port->dev);
1175 dev_err(&port->portdev->vdev->dev,
1176 "Error %d creating device for port %u\n",
1177 err, id);
1178 goto free_cdev;
1179 }
1180
1181 spin_lock_init(&port->inbuf_lock);
1182 init_waitqueue_head(&port->waitqueue);
1183
1184 /* Fill the in_vq with buffers so the host can send us data. */
1185 nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
1186 if (!nr_added_bufs) {
1187 dev_err(port->dev, "Error allocating inbufs\n");
1188 err = -ENOMEM;
1189 goto free_device;
1190 }
1191
1192 /*
1193 * If we're not using multiport support, this has to be a console port
1194 */
1195 if (!use_multiport(port->portdev)) {
1196 err = init_port_console(port);
1197 if (err)
1198 goto free_inbufs;
1199 }
1200
1201 spin_lock_irq(&portdev->ports_lock);
1202 list_add_tail(&port->list, &port->portdev->ports);
1203 spin_unlock_irq(&portdev->ports_lock);
1204
1205 /*
1206 * Tell the Host we're set so that it can send us various
1207 * configuration parameters for this port (eg, port name,
1208 * caching, whether this is a console port, etc.)
1209 */
1210 send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
1211
1212 if (pdrvdata.debugfs_dir) {
1213 /*
1214 * Finally, create the debugfs file that we can use to
1215 * inspect a port's state at any time
1216 */
1217 sprintf(debugfs_name, "vport%up%u",
1218 port->portdev->drv_index, id);
1219 port->debugfs_file = debugfs_create_file(debugfs_name, 0444,
1220 pdrvdata.debugfs_dir,
1221 port,
1222 &port_debugfs_ops);
1223 }
1224 return 0;
1225
1226free_inbufs:
1227 while ((buf = port->in_vq->vq_ops->detach_unused_buf(port->in_vq)))
1228 free_buf(buf);
1229free_device:
1230 device_destroy(pdrvdata.class, port->dev->devt);
1231free_cdev:
1232 cdev_del(&port->cdev);
1233free_port:
1234 kfree(port);
1235fail:
1236 return err;
1237}
1238 1338
1239/* 1339 if (!use_multiport(portdev)) {
1240 * The workhandler for config-space updates. 1340 struct port *port;
1241 * 1341 u16 rows, cols;
1242 * This is called when ports are hot-added.
1243 */
1244static void config_work_handler(struct work_struct *work)
1245{
1246 struct virtio_console_multiport_conf virtconconf;
1247 struct ports_device *portdev;
1248 struct virtio_device *vdev;
1249 int err;
1250 1342
1251 portdev = container_of(work, struct ports_device, config_work); 1343 vdev->config->get(vdev,
1344 offsetof(struct virtio_console_config, cols),
1345 &cols, sizeof(u16));
1346 vdev->config->get(vdev,
1347 offsetof(struct virtio_console_config, rows),
1348 &rows, sizeof(u16));
1252 1349
1253 vdev = portdev->vdev; 1350 port = find_port_by_id(portdev, 0);
1254 vdev->config->get(vdev, 1351 set_console_size(port, rows, cols);
1255 offsetof(struct virtio_console_multiport_conf,
1256 nr_ports),
1257 &virtconconf.nr_ports,
1258 sizeof(virtconconf.nr_ports));
1259 1352
1260 if (portdev->config.nr_ports == virtconconf.nr_ports) {
1261 /* 1353 /*
1262 * Port 0 got hot-added. Since we already did all the 1354 * We'll use this way of resizing only for legacy
1263 * other initialisation for it, just tell the Host 1355 * support. For newer userspace
1264 * that the port is ready if we find the port. In 1356 * (VIRTIO_CONSOLE_F_MULTPORT+), use control messages
1265 * case the port was hot-removed earlier, we call 1357 * to indicate console size changes so that it can be
1266 * add_port to add the port. 1358 * done per-port.
1267 */ 1359 */
1268 struct port *port; 1360 resize_console(port);
1269
1270 port = find_port_by_id(portdev, 0);
1271 if (!port)
1272 add_port(portdev, 0);
1273 else
1274 send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
1275 return;
1276 }
1277 if (virtconconf.nr_ports > portdev->config.max_nr_ports) {
1278 dev_warn(&vdev->dev,
1279 "More ports specified (%u) than allowed (%u)",
1280 portdev->config.nr_ports + 1,
1281 portdev->config.max_nr_ports);
1282 return;
1283 }
1284 if (virtconconf.nr_ports < portdev->config.nr_ports)
1285 return;
1286
1287 /* Hot-add ports */
1288 while (virtconconf.nr_ports - portdev->config.nr_ports) {
1289 err = add_port(portdev, portdev->config.nr_ports);
1290 if (err)
1291 break;
1292 portdev->config.nr_ports++;
1293 } 1361 }
1294} 1362}
1295 1363
@@ -1414,7 +1482,6 @@ static const struct file_operations portdev_fops = {
1414static int __devinit virtcons_probe(struct virtio_device *vdev) 1482static int __devinit virtcons_probe(struct virtio_device *vdev)
1415{ 1483{
1416 struct ports_device *portdev; 1484 struct ports_device *portdev;
1417 u32 i;
1418 int err; 1485 int err;
1419 bool multiport; 1486 bool multiport;
1420 1487
@@ -1443,37 +1510,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
1443 } 1510 }
1444 1511
1445 multiport = false; 1512 multiport = false;
1446 portdev->config.nr_ports = 1;
1447 portdev->config.max_nr_ports = 1; 1513 portdev->config.max_nr_ports = 1;
1448#if 0 /* Multiport is not quite ready yet --RR */
1449 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { 1514 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
1450 multiport = true; 1515 multiport = true;
1451 vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; 1516 vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT;
1452 1517
1453 vdev->config->get(vdev, 1518 vdev->config->get(vdev, offsetof(struct virtio_console_config,
1454 offsetof(struct virtio_console_multiport_conf, 1519 max_nr_ports),
1455 nr_ports),
1456 &portdev->config.nr_ports,
1457 sizeof(portdev->config.nr_ports));
1458 vdev->config->get(vdev,
1459 offsetof(struct virtio_console_multiport_conf,
1460 max_nr_ports),
1461 &portdev->config.max_nr_ports, 1520 &portdev->config.max_nr_ports,
1462 sizeof(portdev->config.max_nr_ports)); 1521 sizeof(portdev->config.max_nr_ports));
1463 if (portdev->config.nr_ports > portdev->config.max_nr_ports) {
1464 dev_warn(&vdev->dev,
1465 "More ports (%u) specified than allowed (%u). Will init %u ports.",
1466 portdev->config.nr_ports,
1467 portdev->config.max_nr_ports,
1468 portdev->config.max_nr_ports);
1469
1470 portdev->config.nr_ports = portdev->config.max_nr_ports;
1471 }
1472 } 1522 }
1473 1523
1474 /* Let the Host know we support multiple ports.*/ 1524 /* Let the Host know we support multiple ports.*/
1475 vdev->config->finalize_features(vdev); 1525 vdev->config->finalize_features(vdev);
1476#endif
1477 1526
1478 err = init_vqs(portdev); 1527 err = init_vqs(portdev);
1479 if (err < 0) { 1528 if (err < 0) {
@@ -1489,7 +1538,6 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
1489 1538
1490 spin_lock_init(&portdev->cvq_lock); 1539 spin_lock_init(&portdev->cvq_lock);
1491 INIT_WORK(&portdev->control_work, &control_work_handler); 1540 INIT_WORK(&portdev->control_work, &control_work_handler);
1492 INIT_WORK(&portdev->config_work, &config_work_handler);
1493 1541
1494 nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock); 1542 nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
1495 if (!nr_added_bufs) { 1543 if (!nr_added_bufs) {
@@ -1498,16 +1546,22 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
1498 err = -ENOMEM; 1546 err = -ENOMEM;
1499 goto free_vqs; 1547 goto free_vqs;
1500 } 1548 }
1549 } else {
1550 /*
1551 * For backward compatibility: Create a console port
1552 * if we're running on older host.
1553 */
1554 add_port(portdev, 0);
1501 } 1555 }
1502 1556
1503 for (i = 0; i < portdev->config.nr_ports; i++) 1557 __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
1504 add_port(portdev, i); 1558 VIRTIO_CONSOLE_DEVICE_READY, 1);
1505
1506 /* Start using the new console output. */
1507 early_put_chars = NULL;
1508 return 0; 1559 return 0;
1509 1560
1510free_vqs: 1561free_vqs:
1562 /* The host might want to notify mgmt sw about device add failure */
1563 __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
1564 VIRTIO_CONSOLE_DEVICE_READY, 0);
1511 vdev->config->del_vqs(vdev); 1565 vdev->config->del_vqs(vdev);
1512 kfree(portdev->in_vqs); 1566 kfree(portdev->in_vqs);
1513 kfree(portdev->out_vqs); 1567 kfree(portdev->out_vqs);
@@ -1529,17 +1583,16 @@ static void virtcons_remove(struct virtio_device *vdev)
1529 portdev = vdev->priv; 1583 portdev = vdev->priv;
1530 1584
1531 cancel_work_sync(&portdev->control_work); 1585 cancel_work_sync(&portdev->control_work);
1532 cancel_work_sync(&portdev->config_work);
1533 1586
1534 list_for_each_entry_safe(port, port2, &portdev->ports, list) 1587 list_for_each_entry_safe(port, port2, &portdev->ports, list)
1535 remove_port(port); 1588 remove_port(port);
1536 1589
1537 unregister_chrdev(portdev->chr_major, "virtio-portsdev"); 1590 unregister_chrdev(portdev->chr_major, "virtio-portsdev");
1538 1591
1539 while ((buf = portdev->c_ivq->vq_ops->get_buf(portdev->c_ivq, &len))) 1592 while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
1540 free_buf(buf); 1593 free_buf(buf);
1541 1594
1542 while ((buf = portdev->c_ivq->vq_ops->detach_unused_buf(portdev->c_ivq))) 1595 while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
1543 free_buf(buf); 1596 free_buf(buf);
1544 1597
1545 vdev->config->del_vqs(vdev); 1598 vdev->config->del_vqs(vdev);
@@ -1556,6 +1609,7 @@ static struct virtio_device_id id_table[] = {
1556 1609
1557static unsigned int features[] = { 1610static unsigned int features[] = {
1558 VIRTIO_CONSOLE_F_SIZE, 1611 VIRTIO_CONSOLE_F_SIZE,
1612 VIRTIO_CONSOLE_F_MULTIPORT,
1559}; 1613};
1560 1614
1561static struct virtio_driver virtio_console = { 1615static struct virtio_driver virtio_console = {