diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-26 19:36:11 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-26 19:36:11 -0400 |
| commit | 0644f186fc9d77bb5bd198369e59fb28927a3692 (patch) | |
| tree | 7e0f70b944e564686167e3ec9ad00e47cec4b80f | |
| parent | 0871062bf9c6e6f0cc91247b3e743a37b87a970f (diff) | |
| parent | 5c60300d68da32ca77f7f978039dc72bfc78b06b (diff) | |
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio fixups from Michael Tsirkin:
- Latest header update will break QEMU (if it's rebuilt with the new
header) - and it seems that the code there is so fragile that any
change in this header will break it. Add a better interface so users
do not need to change their code every time that header changes.
- Fix virtio console for spec compliance.
* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
virtio_console: reset on out of memory
virtio_console: move removal code
virtio_console: drop custom control queue cleanup
virtio_console: free buffers after reset
virtio: add ability to iterate over vqs
virtio_console: don't tie bufs to a vq
virtio_balloon: add array of stat names
| -rw-r--r-- | drivers/char/virtio_console.c | 157 | ||||
| -rw-r--r-- | include/linux/virtio.h | 3 | ||||
| -rw-r--r-- | include/uapi/linux/virtio_balloon.h | 15 |
3 files changed, 89 insertions, 86 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 468f06134012..21085515814f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -422,7 +422,7 @@ static void reclaim_dma_bufs(void) | |||
| 422 | } | 422 | } |
| 423 | } | 423 | } |
| 424 | 424 | ||
| 425 | static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size, | 425 | static struct port_buffer *alloc_buf(struct virtio_device *vdev, size_t buf_size, |
| 426 | int pages) | 426 | int pages) |
| 427 | { | 427 | { |
| 428 | struct port_buffer *buf; | 428 | struct port_buffer *buf; |
| @@ -445,16 +445,16 @@ static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size, | |||
| 445 | return buf; | 445 | return buf; |
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | if (is_rproc_serial(vq->vdev)) { | 448 | if (is_rproc_serial(vdev)) { |
| 449 | /* | 449 | /* |
| 450 | * Allocate DMA memory from ancestor. When a virtio | 450 | * Allocate DMA memory from ancestor. When a virtio |
| 451 | * device is created by remoteproc, the DMA memory is | 451 | * device is created by remoteproc, the DMA memory is |
| 452 | * associated with the grandparent device: | 452 | * associated with the grandparent device: |
| 453 | * vdev => rproc => platform-dev. | 453 | * vdev => rproc => platform-dev. |
| 454 | */ | 454 | */ |
| 455 | if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent) | 455 | if (!vdev->dev.parent || !vdev->dev.parent->parent) |
| 456 | goto free_buf; | 456 | goto free_buf; |
| 457 | buf->dev = vq->vdev->dev.parent->parent; | 457 | buf->dev = vdev->dev.parent->parent; |
| 458 | 458 | ||
| 459 | /* Increase device refcnt to avoid freeing it */ | 459 | /* Increase device refcnt to avoid freeing it */ |
| 460 | get_device(buf->dev); | 460 | get_device(buf->dev); |
| @@ -838,7 +838,7 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
| 838 | 838 | ||
| 839 | count = min((size_t)(32 * 1024), count); | 839 | count = min((size_t)(32 * 1024), count); |
| 840 | 840 | ||
| 841 | buf = alloc_buf(port->out_vq, count, 0); | 841 | buf = alloc_buf(port->portdev->vdev, count, 0); |
| 842 | if (!buf) | 842 | if (!buf) |
| 843 | return -ENOMEM; | 843 | return -ENOMEM; |
| 844 | 844 | ||
| @@ -957,7 +957,7 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
| 957 | if (ret < 0) | 957 | if (ret < 0) |
| 958 | goto error_out; | 958 | goto error_out; |
| 959 | 959 | ||
| 960 | buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); | 960 | buf = alloc_buf(port->portdev->vdev, 0, pipe->nrbufs); |
| 961 | if (!buf) { | 961 | if (!buf) { |
| 962 | ret = -ENOMEM; | 962 | ret = -ENOMEM; |
| 963 | goto error_out; | 963 | goto error_out; |
| @@ -1374,7 +1374,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
| 1374 | 1374 | ||
| 1375 | nr_added_bufs = 0; | 1375 | nr_added_bufs = 0; |
| 1376 | do { | 1376 | do { |
| 1377 | buf = alloc_buf(vq, PAGE_SIZE, 0); | 1377 | buf = alloc_buf(vq->vdev, PAGE_SIZE, 0); |
| 1378 | if (!buf) | 1378 | if (!buf) |
| 1379 | break; | 1379 | break; |
| 1380 | 1380 | ||
| @@ -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,24 +1974,54 @@ 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);< |
