diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2013-08-08 23:30:39 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-08-08 23:30:39 -0400 |
commit | 11489736177c5930514482b4db7af862d945335d (patch) | |
tree | 8590ec4ba037b79c94982e15922fe50a1f0193a3 /drivers/char | |
parent | 3f0d0c9b47e09d47fcb755fed786a1ee88e110b5 (diff) | |
parent | 6c2580c501c660fdfb506061e016d84570fceba1 (diff) |
Merge branch 'master' into virtio-next
The next commit gets conflicts because it relies on patches which were
cc:stable and thus had to be merged into Linus' tree before the coming
merge window. So pull in master now.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/parisc-agp.c | 6 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 70 |
2 files changed, 52 insertions, 24 deletions
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index bf5d2477cb77..15f2e7025b78 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c | |||
@@ -129,7 +129,8 @@ parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
129 | off_t j, io_pg_start; | 129 | off_t j, io_pg_start; |
130 | int io_pg_count; | 130 | int io_pg_count; |
131 | 131 | ||
132 | if (type != 0 || mem->type != 0) { | 132 | if (type != mem->type || |
133 | agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) { | ||
133 | return -EINVAL; | 134 | return -EINVAL; |
134 | } | 135 | } |
135 | 136 | ||
@@ -175,7 +176,8 @@ parisc_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
175 | struct _parisc_agp_info *info = &parisc_agp_info; | 176 | struct _parisc_agp_info *info = &parisc_agp_info; |
176 | int i, io_pg_start, io_pg_count; | 177 | int i, io_pg_start, io_pg_count; |
177 | 178 | ||
178 | if (type != 0 || mem->type != 0) { | 179 | if (type != mem->type || |
180 | agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) { | ||
179 | return -EINVAL; | 181 | return -EINVAL; |
180 | } | 182 | } |
181 | 183 | ||
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 5b60956edc28..d0e75aa904ac 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -272,9 +272,12 @@ static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev, | |||
272 | unsigned long flags; | 272 | unsigned long flags; |
273 | 273 | ||
274 | spin_lock_irqsave(&portdev->ports_lock, flags); | 274 | spin_lock_irqsave(&portdev->ports_lock, flags); |
275 | list_for_each_entry(port, &portdev->ports, list) | 275 | list_for_each_entry(port, &portdev->ports, list) { |
276 | if (port->cdev->dev == dev) | 276 | if (port->cdev->dev == dev) { |
277 | kref_get(&port->kref); | ||
277 | goto out; | 278 | goto out; |
279 | } | ||
280 | } | ||
278 | port = NULL; | 281 | port = NULL; |
279 | out: | 282 | out: |
280 | spin_unlock_irqrestore(&portdev->ports_lock, flags); | 283 | spin_unlock_irqrestore(&portdev->ports_lock, flags); |
@@ -746,6 +749,10 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
746 | 749 | ||
747 | port = filp->private_data; | 750 | port = filp->private_data; |
748 | 751 | ||
752 | /* Port is hot-unplugged. */ | ||
753 | if (!port->guest_connected) | ||
754 | return -ENODEV; | ||
755 | |||
749 | if (!port_has_data(port)) { | 756 | if (!port_has_data(port)) { |
750 | /* | 757 | /* |
751 | * If nothing's connected on the host just return 0 in | 758 | * If nothing's connected on the host just return 0 in |
@@ -762,7 +769,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
762 | if (ret < 0) | 769 | if (ret < 0) |
763 | return ret; | 770 | return ret; |
764 | } | 771 | } |
765 | /* Port got hot-unplugged. */ | 772 | /* Port got hot-unplugged while we were waiting above. */ |
766 | if (!port->guest_connected) | 773 | if (!port->guest_connected) |
767 | return -ENODEV; | 774 | return -ENODEV; |
768 | /* | 775 | /* |
@@ -932,13 +939,25 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
932 | if (is_rproc_serial(port->out_vq->vdev)) | 939 | if (is_rproc_serial(port->out_vq->vdev)) |
933 | return -EINVAL; | 940 | return -EINVAL; |
934 | 941 | ||
942 | /* | ||
943 | * pipe->nrbufs == 0 means there are no data to transfer, | ||
944 | * so this returns just 0 for no data. | ||
945 | */ | ||
946 | pipe_lock(pipe); | ||
947 | if (!pipe->nrbufs) { | ||
948 | ret = 0; | ||
949 | goto error_out; | ||
950 | } | ||
951 | |||
935 | ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); | 952 | ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); |
936 | if (ret < 0) | 953 | if (ret < 0) |
937 | return ret; | 954 | goto error_out; |
938 | 955 | ||
939 | buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); | 956 | buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); |
940 | if (!buf) | 957 | if (!buf) { |
941 | return -ENOMEM; | 958 | ret = -ENOMEM; |
959 | goto error_out; | ||
960 | } | ||
942 | 961 | ||
943 | sgl.n = 0; | 962 | sgl.n = 0; |
944 | sgl.len = 0; | 963 | sgl.len = 0; |
@@ -946,12 +965,17 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
946 | sgl.sg = buf->sg; | 965 | sgl.sg = buf->sg; |
947 | sg_init_table(sgl.sg, sgl.size); | 966 | sg_init_table(sgl.sg, sgl.size); |
948 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); | 967 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); |
968 | pipe_unlock(pipe); | ||
949 | if (likely(ret > 0)) | 969 | if (likely(ret > 0)) |
950 | ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); | 970 | ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); |
951 | 971 | ||
952 | if (unlikely(ret <= 0)) | 972 | if (unlikely(ret <= 0)) |
953 | free_buf(buf, true); | 973 | free_buf(buf, true); |
954 | return ret; | 974 | return ret; |
975 | |||
976 | error_out: | ||
977 | pipe_unlock(pipe); | ||
978 | return ret; | ||
955 | } | 979 | } |
956 | 980 | ||
957 | static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | 981 | static unsigned int port_fops_poll(struct file *filp, poll_table *wait) |
@@ -1019,14 +1043,14 @@ static int port_fops_open(struct inode *inode, struct file *filp) | |||
1019 | struct port *port; | 1043 | struct port *port; |
1020 | int ret; | 1044 | int ret; |
1021 | 1045 | ||
1046 | /* We get the port with a kref here */ | ||
1022 | port = find_port_by_devt(cdev->dev); | 1047 | port = find_port_by_devt(cdev->dev); |
1048 | if (!port) { | ||
1049 | /* Port was unplugged before we could proceed */ | ||
1050 | return -ENXIO; | ||
1051 | } | ||
1023 | filp->private_data = port; | 1052 | filp->private_data = port; |
1024 | 1053 | ||
1025 | /* Prevent against a port getting hot-unplugged at the same time */ | ||
1026 | spin_lock_irq(&port->portdev->ports_lock); | ||
1027 | kref_get(&port->kref); | ||
1028 | spin_unlock_irq(&port->portdev->ports_lock); | ||
1029 | |||
1030 | /* | 1054 | /* |
1031 | * Don't allow opening of console port devices -- that's done | 1055 | * Don't allow opening of console port devices -- that's done |
1032 | * via /dev/hvc | 1056 | * via /dev/hvc |
@@ -1498,14 +1522,6 @@ static void remove_port(struct kref *kref) | |||
1498 | 1522 | ||
1499 | port = container_of(kref, struct port, kref); | 1523 | port = container_of(kref, struct port, kref); |
1500 | 1524 | ||
1501 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
1502 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1503 | cdev_del(port->cdev); | ||
1504 | |||
1505 | kfree(port->name); | ||
1506 | |||
1507 | debugfs_remove(port->debugfs_file); | ||
1508 | |||
1509 | kfree(port); | 1525 | kfree(port); |
1510 | } | 1526 | } |
1511 | 1527 | ||
@@ -1544,12 +1560,14 @@ static void unplug_port(struct port *port) | |||
1544 | 1560 | ||
1545 | spin_lock_irq(&port->inbuf_lock); | 1561 | spin_lock_irq(&port->inbuf_lock); |
1546 | if (port->guest_connected) { | 1562 | if (port->guest_connected) { |
1563 | /* Let the app know the port is going down. */ | ||
1564 | send_sigio_to_port(port); | ||
1565 | |||
1566 | /* Do this after sigio is actually sent */ | ||
1547 | port->guest_connected = false; | 1567 | port->guest_connected = false; |
1548 | port->host_connected = false; | 1568 | port->host_connected = false; |
1549 | wake_up_interruptible(&port->waitqueue); | ||
1550 | 1569 | ||
1551 | /* Let the app know the port is going down. */ | 1570 | wake_up_interruptible(&port->waitqueue); |
1552 | send_sigio_to_port(port); | ||
1553 | } | 1571 | } |
1554 | spin_unlock_irq(&port->inbuf_lock); | 1572 | spin_unlock_irq(&port->inbuf_lock); |
1555 | 1573 | ||
@@ -1569,6 +1587,14 @@ static void unplug_port(struct port *port) | |||
1569 | */ | 1587 | */ |
1570 | port->portdev = NULL; | 1588 | port->portdev = NULL; |
1571 | 1589 | ||
1590 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
1591 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1592 | cdev_del(port->cdev); | ||
1593 | |||
1594 | kfree(port->name); | ||
1595 | |||
1596 | debugfs_remove(port->debugfs_file); | ||
1597 | |||
1572 | /* | 1598 | /* |
1573 | * Locks around here are not necessary - a port can't be | 1599 | * Locks around here are not necessary - a port can't be |
1574 | * opened after we removed the port struct from ports_list | 1600 | * opened after we removed the port struct from ports_list |