diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/char/virtio_console.c | 70 | ||||
| -rw-r--r-- | drivers/scsi/virtio_scsi.c | 2 |
2 files changed, 49 insertions, 23 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 1b456fe9b87a..fc45567ad3ac 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 | ||
| @@ -1539,12 +1555,14 @@ static void unplug_port(struct port *port) | |||
| 1539 | spin_unlock_irq(&port->portdev->ports_lock); | 1555 | spin_unlock_irq(&port->portdev->ports_lock); |
| 1540 | 1556 | ||
| 1541 | if (port->guest_connected) { | 1557 | if (port->guest_connected) { |
| 1558 | /* Let the app know the port is going down. */ | ||
| 1559 | send_sigio_to_port(port); | ||
| 1560 | |||
| 1561 | /* Do this after sigio is actually sent */ | ||
| 1542 | port->guest_connected = false; | 1562 | port->guest_connected = false; |
| 1543 | port->host_connected = false; | 1563 | port->host_connected = false; |
| 1544 | wake_up_interruptible(&port->waitqueue); | ||
| 1545 | 1564 | ||
| 1546 | /* Let the app know the port is going down. */ | 1565 | wake_up_interruptible(&port->waitqueue); |
| 1547 | send_sigio_to_port(port); | ||
| 1548 | } | 1566 | } |
| 1549 | 1567 | ||
| 1550 | if (is_console_port(port)) { | 1568 | if (is_console_port(port)) { |
| @@ -1563,6 +1581,14 @@ static void unplug_port(struct port *port) | |||
| 1563 | */ | 1581 | */ |
| 1564 | port->portdev = NULL; | 1582 | port->portdev = NULL; |
| 1565 | 1583 | ||
| 1584 | sysfs_remove_group(&port->dev->kobj, &port_attribute_group); | ||
| 1585 | device_destroy(pdrvdata.class, port->dev->devt); | ||
| 1586 | cdev_del(port->cdev); | ||
| 1587 | |||
| 1588 | kfree(port->name); | ||
| 1589 | |||
| 1590 | debugfs_remove(port->debugfs_file); | ||
| 1591 | |||
| 1566 | /* | 1592 | /* |
| 1567 | * Locks around here are not necessary - a port can't be | 1593 | * Locks around here are not necessary - a port can't be |
| 1568 | * opened after we removed the port struct from ports_list | 1594 | * opened after we removed the port struct from ports_list |
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 2168258fb2c3..74b88efde6ad 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
| @@ -751,7 +751,7 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) | |||
| 751 | 751 | ||
| 752 | vscsi->affinity_hint_set = true; | 752 | vscsi->affinity_hint_set = true; |
| 753 | } else { | 753 | } else { |
| 754 | for (i = 0; i < vscsi->num_queues - VIRTIO_SCSI_VQ_BASE; i++) | 754 | for (i = 0; i < vscsi->num_queues; i++) |
| 755 | virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); | 755 | virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); |
| 756 | 756 | ||
| 757 | vscsi->affinity_hint_set = false; | 757 | vscsi->affinity_hint_set = false; |
