Allocate vrings use dma_alloc_coherent is a common way in kernel. As the
memory interacted between two systems should use consistent memory to
avoid caching effects, same as device page memory.

The orginal way use __get_free_pages and dma_map_single to allocate and
map vring, but not use dma_sync_single_for_cpu/device api to sync the
changes of vring between EP and RC, which will cause memory
synchronization problem for those devices which don't support hardware
dma coherent.

Signed-off-by: Joakim Zhang <qiangqing.zh...@nxp.com>
Signed-off-by: Sherry Sun <sherry....@nxp.com>
---
 drivers/misc/mic/host/mic_main.c  | 15 +++--------
 drivers/misc/mic/vop/vop_vringh.c | 43 +++++++++----------------------
 2 files changed, 16 insertions(+), 42 deletions(-)

diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
index ea4608527ea0..ebacaa35cb47 100644
--- a/drivers/misc/mic/host/mic_main.c
+++ b/drivers/misc/mic/host/mic_main.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/poll.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/mic_common.h>
 #include "../common/mic_dev.h"
@@ -48,18 +49,11 @@ static struct ida g_mic_ida;
 /* Initialize the device page */
 static int mic_dp_init(struct mic_device *mdev)
 {
-       mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
+       mdev->dp = dma_alloc_coherent(&mdev->pdev->dev, MIC_DP_SIZE,
+                                     &mdev->dp_dma_addr, GFP_KERNEL);
        if (!mdev->dp)
                return -ENOMEM;
 
-       mdev->dp_dma_addr = mic_map_single(mdev,
-               mdev->dp, MIC_DP_SIZE);
-       if (mic_map_error(mdev->dp_dma_addr)) {
-               kfree(mdev->dp);
-               dev_err(&mdev->pdev->dev, "%s %d err %d\n",
-                       __func__, __LINE__, -ENOMEM);
-               return -ENOMEM;
-       }
        mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
        mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
        return 0;
@@ -68,8 +62,7 @@ static int mic_dp_init(struct mic_device *mdev)
 /* Uninitialize the device page */
 static void mic_dp_uninit(struct mic_device *mdev)
 {
-       mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE);
-       kfree(mdev->dp);
+       dma_free_coherent(&mdev->pdev->dev, MIC_DP_SIZE, mdev->dp, 
mdev->dp_dma_addr);
 }
 
 /**
diff --git a/drivers/misc/mic/vop/vop_vringh.c 
b/drivers/misc/mic/vop/vop_vringh.c
index 7014ffe88632..2cc3c22482b5 100644
--- a/drivers/misc/mic/vop/vop_vringh.c
+++ b/drivers/misc/mic/vop/vop_vringh.c
@@ -298,9 +298,8 @@ static int vop_virtio_add_device(struct vop_vdev *vdev,
                mutex_init(&vvr->vr_mutex);
                vr_size = PAGE_ALIGN(round_up(vring_size(num, 
MIC_VIRTIO_RING_ALIGN), 4) +
                        sizeof(struct _mic_vring_info));
-               vr->va = (void *)
-                       __get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                        get_order(vr_size));
+               vr->va = dma_alloc_coherent(vop_dev(vdev), vr_size, &vr_addr,
+                                           GFP_KERNEL);
                if (!vr->va) {
                        ret = -ENOMEM;
                        dev_err(vop_dev(vdev), "%s %d err %d\n",
@@ -310,15 +309,6 @@ static int vop_virtio_add_device(struct vop_vdev *vdev,
                vr->len = vr_size;
                vr->info = vr->va + round_up(vring_size(num, 
MIC_VIRTIO_RING_ALIGN), 4);
                vr->info->magic = cpu_to_le32(MIC_MAGIC + vdev->virtio_id + i);
-               vr_addr = dma_map_single(&vpdev->dev, vr->va, vr_size,
-                                        DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(&vpdev->dev, vr_addr)) {
-                       free_pages((unsigned long)vr->va, get_order(vr_size));
-                       ret = -ENOMEM;
-                       dev_err(vop_dev(vdev), "%s %d err %d\n",
-                               __func__, __LINE__, ret);
-                       goto err;
-               }
                vqconfig[i].address = cpu_to_le64(vr_addr);
 
                vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
@@ -339,11 +329,8 @@ static int vop_virtio_add_device(struct vop_vdev *vdev,
                dev_dbg(&vpdev->dev,
                        "%s %d index %d va %p info %p vr_size 0x%x\n",
                        __func__, __LINE__, i, vr->va, vr->info, vr_size);
-               vvr->buf = (void *)__get_free_pages(GFP_KERNEL,
-                                       get_order(VOP_INT_DMA_BUF_SIZE));
-               vvr->buf_da = dma_map_single(&vpdev->dev,
-                                         vvr->buf, VOP_INT_DMA_BUF_SIZE,
-                                         DMA_BIDIRECTIONAL);
+               vvr->buf = dma_alloc_coherent(vop_dev(vdev), 
VOP_INT_DMA_BUF_SIZE,
+                                             &vvr->buf_da, GFP_KERNEL);
        }
 
        snprintf(irqname, sizeof(irqname), "vop%dvirtio%d", vpdev->index,
@@ -382,10 +369,8 @@ static int vop_virtio_add_device(struct vop_vdev *vdev,
        for (j = 0; j < i; j++) {
                struct vop_vringh *vvr = &vdev->vvr[j];
 
-               dma_unmap_single(&vpdev->dev, le64_to_cpu(vqconfig[j].address),
-                                vvr->vring.len, DMA_BIDIRECTIONAL);
-               free_pages((unsigned long)vvr->vring.va,
-                          get_order(vvr->vring.len));
+               dma_free_coherent(vop_dev(vdev), vvr->vring.len, vvr->vring.va,
+                                 le64_to_cpu(vqconfig[j].address));
        }
        return ret;
 }
@@ -433,17 +418,12 @@ static void vop_virtio_del_device(struct vop_vdev *vdev)
        for (i = 0; i < vdev->dd->num_vq; i++) {
                struct vop_vringh *vvr = &vdev->vvr[i];
 
-               dma_unmap_single(&vpdev->dev,
-                                vvr->buf_da, VOP_INT_DMA_BUF_SIZE,
-                                DMA_BIDIRECTIONAL);
-               free_pages((unsigned long)vvr->buf,
-                          get_order(VOP_INT_DMA_BUF_SIZE));
+               dma_free_coherent(vop_dev(vdev), VOP_INT_DMA_BUF_SIZE,
+                                 vvr->buf, vvr->buf_da);
                vringh_kiov_cleanup(&vvr->riov);
                vringh_kiov_cleanup(&vvr->wiov);
-               dma_unmap_single(&vpdev->dev, le64_to_cpu(vqconfig[i].address),
-                                vvr->vring.len, DMA_BIDIRECTIONAL);
-               free_pages((unsigned long)vvr->vring.va,
-                          get_order(vvr->vring.len));
+               dma_free_coherent(vop_dev(vdev), vvr->vring.len, vvr->vring.va,
+                                 le64_to_cpu(vqconfig[i].address));
        }
        /*
         * Order the type update with previous stores. This write barrier
@@ -1047,6 +1027,7 @@ vop_query_offset(struct vop_vdev *vdev, unsigned long 
offset,
                 unsigned long *size, unsigned long *pa)
 {
        struct vop_device *vpdev = vdev->vpdev;
+       struct mic_vqconfig *vqconfig = mic_vq_config(vdev->dd);
        unsigned long start = MIC_DP_SIZE;
        int i;
 
@@ -1068,7 +1049,7 @@ vop_query_offset(struct vop_vdev *vdev, unsigned long 
offset,
                struct vop_vringh *vvr = &vdev->vvr[i];
 
                if (offset == start) {
-                       *pa = virt_to_phys(vvr->vring.va);
+                       *pa = vqconfig[i].address;
                        *size = vvr->vring.len;
                        return 0;
                }
-- 
2.17.1

Reply via email to