vop: vringh: Do not crash if no DMA channel
authorVincent Whitchurch <vincent.whitchurch@axis.com>
Wed, 16 Jan 2019 16:32:50 +0000 (17:32 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Jan 2019 10:43:17 +0000 (11:43 +0100)
Fallback gracefully if no DMA channel is provided instead of
dereferencing NULL pointers.

Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mic/vop/vop_vringh.c

index 4267fa0..0bac8bc 100644 (file)
@@ -531,12 +531,12 @@ static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf,
        void __iomem *dbuf = vpdev->hw_ops->ioremap(vpdev, daddr, len);
        struct vop_vringh *vvr = &vdev->vvr[vr_idx];
        struct vop_info *vi = dev_get_drvdata(&vpdev->dev);
-       size_t dma_alignment = 1 << vi->dma_ch->device->copy_align;
-       bool x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+       size_t dma_alignment;
+       bool x200;
        size_t dma_offset, partlen;
        int err;
 
-       if (!VOP_USE_DMA) {
+       if (!VOP_USE_DMA || !vi->dma_ch) {
                if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
                        err = -EFAULT;
                        dev_err(vop_dev(vdev), "%s %d err %d\n",
@@ -548,6 +548,9 @@ static int vop_virtio_copy_to_user(struct vop_vdev *vdev, void __user *ubuf,
                goto err;
        }
 
+       dma_alignment = 1 << vi->dma_ch->device->copy_align;
+       x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+
        dma_offset = daddr - round_down(daddr, dma_alignment);
        daddr -= dma_offset;
        len += dma_offset;
@@ -606,18 +609,23 @@ static int vop_virtio_copy_from_user(struct vop_vdev *vdev, void __user *ubuf,
        void __iomem *dbuf = vpdev->hw_ops->ioremap(vpdev, daddr, len);
        struct vop_vringh *vvr = &vdev->vvr[vr_idx];
        struct vop_info *vi = dev_get_drvdata(&vdev->vpdev->dev);
-       size_t dma_alignment = 1 << vi->dma_ch->device->copy_align;
-       bool x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+       size_t dma_alignment;
+       bool x200;
        size_t partlen;
-       bool dma = VOP_USE_DMA;
+       bool dma = VOP_USE_DMA && vi->dma_ch;
        int err = 0;
 
-       if (daddr & (dma_alignment - 1)) {
-               vdev->tx_dst_unaligned += len;
-               dma = false;
-       } else if (ALIGN(len, dma_alignment) > dlen) {
-               vdev->tx_len_unaligned += len;
-               dma = false;
+       if (dma) {
+               dma_alignment = 1 << vi->dma_ch->device->copy_align;
+               x200 = is_dma_copy_aligned(vi->dma_ch->device, 1, 1, 1);
+
+               if (daddr & (dma_alignment - 1)) {
+                       vdev->tx_dst_unaligned += len;
+                       dma = false;
+               } else if (ALIGN(len, dma_alignment) > dlen) {
+                       vdev->tx_len_unaligned += len;
+                       dma = false;
+               }
        }
 
        if (!dma)