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.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 213373b5f17f..44288ce0cb45 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -379,7 +379,7 @@ static ssize_t send_control_msg(struct port *port, unsigned int event,
struct scatterlist sg[1];
struct virtio_console_control cpkt;
struct virtqueue *vq;
- int len;
+ unsigned int len;
if (!use_multiport(port->portdev))
return 0;
@@ -681,6 +681,10 @@ static void resize_console(struct port *port)
struct virtio_device *vdev;
struct winsize ws;
+ /* The port could have been hot-unplugged */
+ if (!port)
+ return;
+
vdev = port->portdev->vdev;
if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) {
vdev->config->get(vdev,
@@ -947,11 +951,18 @@ static void handle_control_message(struct ports_device *portdev,
*/
err = sysfs_create_group(&port->dev->kobj,
&port_attribute_group);
- if (err)
+ if (err) {
dev_err(port->dev,
"Error %d creating sysfs device attributes\n",
err);
-
+ } else {
+ /*
+ * Generate a udev event so that appropriate
+ * symlinks can be created based on udev
+ * rules.
+ */
+ kobject_uevent(&port->dev->kobj, KOBJ_CHANGE);
+ }
break;
case VIRTIO_CONSOLE_PORT_REMOVE:
/*
@@ -1071,27 +1082,27 @@ static void config_intr(struct virtio_device *vdev)
static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
{
struct port_buffer *buf;
- unsigned int ret;
- int err;
+ unsigned int nr_added_bufs;
+ int ret;
- ret = 0;
+ nr_added_bufs = 0;
do {
buf = alloc_buf(PAGE_SIZE);
if (!buf)
break;
spin_lock_irq(lock);
- err = add_inbuf(vq, buf);
- if (err < 0) {
+ ret = add_inbuf(vq, buf);
+ if (ret < 0) {
spin_unlock_irq(lock);
free_buf(buf);
break;
}
- ret++;
+ nr_added_bufs++;
spin_unlock_irq(lock);
- } while (err > 0);
+ } while (ret > 0);
- return ret;
+ return nr_added_bufs;
}
static int add_port(struct ports_device *portdev, u32 id)
@@ -1100,6 +1111,7 @@ static int add_port(struct ports_device *portdev, u32 id)
struct port *port;
struct port_buffer *buf;
dev_t devt;
+ unsigned int nr_added_bufs;
int err;
port = kmalloc(sizeof(*port), GFP_KERNEL);
@@ -1144,8 +1156,8 @@ static int add_port(struct ports_device *portdev, u32 id)
init_waitqueue_head(&port->waitqueue);
/* Fill the in_vq with buffers so the host can send us data. */
- err = fill_queue(port->in_vq, &port->inbuf_lock);
- if (!err) {
+ nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
+ if (!nr_added_bufs) {
dev_err(port->dev, "Error allocating inbufs\n");
err = -ENOMEM;
goto free_device;
@@ -1442,12 +1454,14 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
INIT_LIST_HEAD(&portdev->ports);
if (multiport) {
+ unsigned int nr_added_bufs;
+
spin_lock_init(&portdev->cvq_lock);
INIT_WORK(&portdev->control_work, &control_work_handler);
INIT_WORK(&portdev->config_work, &config_work_handler);
- err = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
- if (!err) {
+ nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+ if (!nr_added_bufs) {
dev_err(&vdev->dev,
"Error allocating buffers for control queue\n");
err = -ENOMEM;