diff options
-rw-r--r-- | drivers/char/virtio_console.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 3e56f328b4cb..26a66ffd943e 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -1402,7 +1402,6 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1402 | { | 1402 | { |
1403 | char debugfs_name[16]; | 1403 | char debugfs_name[16]; |
1404 | struct port *port; | 1404 | struct port *port; |
1405 | struct port_buffer *buf; | ||
1406 | dev_t devt; | 1405 | dev_t devt; |
1407 | unsigned int nr_added_bufs; | 1406 | unsigned int nr_added_bufs; |
1408 | int err; | 1407 | int err; |
@@ -1513,8 +1512,6 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
1513 | return 0; | 1512 | return 0; |
1514 | 1513 | ||
1515 | free_inbufs: | 1514 | free_inbufs: |
1516 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
1517 | free_buf(buf, true); | ||
1518 | free_device: | 1515 | free_device: |
1519 | device_destroy(pdrvdata.class, port->dev->devt); | 1516 | device_destroy(pdrvdata.class, port->dev->devt); |
1520 | free_cdev: | 1517 | free_cdev: |
@@ -1539,34 +1536,14 @@ static void remove_port(struct kref *kref) | |||
1539 | 1536 | ||
1540 | static void remove_port_data(struct port *port) | 1537 | static void remove_port_data(struct port *port) |
1541 | { | 1538 | { |
1542 | struct port_buffer *buf; | ||
1543 | |||
1544 | spin_lock_irq(&port->inbuf_lock); | 1539 | spin_lock_irq(&port->inbuf_lock); |
1545 | /* Remove unused data this port might have received. */ | 1540 | /* Remove unused data this port might have received. */ |
1546 | discard_port_data(port); | 1541 | discard_port_data(port); |
1547 | spin_unlock_irq(&port->inbuf_lock); | 1542 | spin_unlock_irq(&port->inbuf_lock); |
1548 | 1543 | ||
1549 | /* Remove buffers we queued up for the Host to send us data in. */ | ||
1550 | do { | ||
1551 | spin_lock_irq(&port->inbuf_lock); | ||
1552 | buf = virtqueue_detach_unused_buf(port->in_vq); | ||
1553 | spin_unlock_irq(&port->inbuf_lock); | ||
1554 | if (buf) | ||
1555 | free_buf(buf, true); | ||
1556 | } while (buf); | ||
1557 | |||
1558 | spin_lock_irq(&port->outvq_lock); | 1544 | spin_lock_irq(&port->outvq_lock); |
1559 | reclaim_consumed_buffers(port); | 1545 | reclaim_consumed_buffers(port); |
1560 | spin_unlock_irq(&port->outvq_lock); | 1546 | spin_unlock_irq(&port->outvq_lock); |
1561 | |||
1562 | /* Free pending buffers from the out-queue. */ | ||
1563 | do { | ||
1564 | spin_lock_irq(&port->outvq_lock); | ||
1565 | buf = virtqueue_detach_unused_buf(port->out_vq); | ||
1566 | spin_unlock_irq(&port->outvq_lock); | ||
1567 | if (buf) | ||
1568 | free_buf(buf, true); | ||
1569 | } while (buf); | ||
1570 | } | 1547 | } |
1571 | 1548 | ||
1572 | /* | 1549 | /* |
@@ -1791,13 +1768,24 @@ static void control_work_handler(struct work_struct *work) | |||
1791 | spin_unlock(&portdev->c_ivq_lock); | 1768 | spin_unlock(&portdev->c_ivq_lock); |
1792 | } | 1769 | } |
1793 | 1770 | ||
1771 | static void flush_bufs(struct virtqueue *vq, bool can_sleep) | ||
1772 | { | ||
1773 | struct port_buffer *buf; | ||
1774 | unsigned int len; | ||
1775 | |||
1776 | while ((buf = virtqueue_get_buf(vq, &len))) | ||
1777 | free_buf(buf, can_sleep); | ||
1778 | } | ||
1779 | |||
1794 | static void out_intr(struct virtqueue *vq) | 1780 | static void out_intr(struct virtqueue *vq) |
1795 | { | 1781 | { |
1796 | struct port *port; | 1782 | struct port *port; |
1797 | 1783 | ||
1798 | port = find_port_by_vq(vq->vdev->priv, vq); | 1784 | port = find_port_by_vq(vq->vdev->priv, vq); |
1799 | if (!port) | 1785 | if (!port) { |
1786 | flush_bufs(vq, false); | ||
1800 | return; | 1787 | return; |
1788 | } | ||
1801 | 1789 | ||
1802 | wake_up_interruptible(&port->waitqueue); | 1790 | wake_up_interruptible(&port->waitqueue); |
1803 | } | 1791 | } |
@@ -1808,8 +1796,10 @@ static void in_intr(struct virtqueue *vq) | |||
1808 | unsigned long flags; | 1796 | unsigned long flags; |
1809 | 1797 | ||
1810 | port = find_port_by_vq(vq->vdev->priv, vq); | 1798 | port = find_port_by_vq(vq->vdev->priv, vq); |
1811 | if (!port) | 1799 | if (!port) { |
1800 | flush_bufs(vq, false); | ||
1812 | return; | 1801 | return; |
1802 | } | ||
1813 | 1803 | ||
1814 | spin_lock_irqsave(&port->inbuf_lock, flags); | 1804 | spin_lock_irqsave(&port->inbuf_lock, flags); |
1815 | port->inbuf = get_inbuf(port); | 1805 | port->inbuf = get_inbuf(port); |
@@ -1984,6 +1974,15 @@ static const struct file_operations portdev_fops = { | |||
1984 | 1974 | ||
1985 | static void remove_vqs(struct ports_device *portdev) | 1975 | static void remove_vqs(struct ports_device *portdev) |
1986 | { | 1976 | { |
1977 | struct virtqueue *vq; | ||
1978 | |||
1979 | virtio_device_for_each_vq(portdev->vdev, vq) { | ||
1980 | struct port_buffer *buf; | ||
1981 | |||
1982 | flush_bufs(vq, true); | ||
1983 | while ((buf = virtqueue_detach_unused_buf(vq))) | ||
1984 | free_buf(buf, true); | ||
1985 | } | ||
1987 | portdev->vdev->config->del_vqs(portdev->vdev); | 1986 | portdev->vdev->config->del_vqs(portdev->vdev); |
1988 | kfree(portdev->in_vqs); | 1987 | kfree(portdev->in_vqs); |
1989 | kfree(portdev->out_vqs); | 1988 | kfree(portdev->out_vqs); |