From: Halil Pasic <pasic@xxxxxxxxxxxxxxxxxx> The hypervisor is supposed to poke the classic notifiers, if these are used, out of band with regards to ccw I/O. So these need to be allocated as DMA memory (which is shared memory for protected virtualization guests). Let us factor out notifiers in a satellite that is allocated as DMA memory to accommodate that. Signed-off-by: Halil Pasic <pasic@xxxxxxxxxxxxxxxxxx> --- drivers/s390/virtio/virtio_ccw.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 156166ae4df4..aa45a6a027ae 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -46,6 +46,11 @@ struct vq_config_block { #define VIRTIO_CCW_CONFIG_SIZE 0x100 /* same as PCI config space size, should be enough for all drivers */ +struct vcdev_dma_area { + unsigned long indicators; + unsigned long indicators2; +}; + struct virtio_ccw_device { struct virtio_device vdev; __u8 *status; @@ -59,8 +64,6 @@ struct virtio_ccw_device { spinlock_t lock; struct mutex io_lock; /* Serializes I/O requests */ struct list_head virtqueues; - unsigned long indicators; - unsigned long indicators2; struct vq_config_block *config_block; dma_addr_t config_block_dma_addr; bool is_thinint; @@ -69,16 +72,18 @@ struct virtio_ccw_device { unsigned int config_ready; void *airq_info; __u64 dma_mask; + struct vcdev_dma_area *dma_area; + dma_addr_t dma_area_dma_addr; }; static inline unsigned long *indicators(struct virtio_ccw_device *vcdev) { - return &vcdev->indicators; + return &vcdev->dma_area->indicators; } static inline unsigned long *indicators2(struct virtio_ccw_device *vcdev) { - return &vcdev->indicators2; + return &vcdev->dma_area->indicators2; } struct vq_info_block_legacy { @@ -1044,6 +1049,8 @@ static void virtio_ccw_release_dev(struct device *_d) vc_dma_free_struct(dev, vcdev->status); vc_dma_free_struct(dev, vcdev->config_block); + __vc_dma_free(&vcdev->vdev, PAGE_SIZE, vcdev->dma_area, + vcdev->dma_area_dma_addr); kfree(vcdev); } @@ -1325,6 +1332,12 @@ static int virtio_ccw_online(struct ccw_device *cdev) ret = -ENOMEM; goto out_free; } + vcdev->dma_area = __vc_dma_alloc(&vcdev->vdev, PAGE_SIZE, + &vcdev->dma_area_dma_addr); + if (!vcdev->dma_area) { + ret = -ENOMEM; + goto out_free; + } vcdev->is_thinint = virtio_ccw_use_airq; /* at least try */ @@ -1363,6 +1376,8 @@ static int virtio_ccw_online(struct ccw_device *cdev) if (vcdev) { vc_dma_free_struct(&vcdev->vdev, vcdev->status); vc_dma_free_struct(&vcdev->vdev, vcdev->config_block); + __vc_dma_free(&vcdev->vdev, PAGE_SIZE, vcdev->dma_area, + vcdev->dma_area_dma_addr); } kfree(vcdev); return ret; -- 2.16.4