summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/misc/mic/scif/scif_map.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/misc/mic/scif/scif_map.h')
-rw-r--r--kernel/drivers/misc/mic/scif/scif_map.h136
1 files changed, 136 insertions, 0 deletions
diff --git a/kernel/drivers/misc/mic/scif/scif_map.h b/kernel/drivers/misc/mic/scif/scif_map.h
new file mode 100644
index 000000000..3e86360ba
--- /dev/null
+++ b/kernel/drivers/misc/mic/scif/scif_map.h
@@ -0,0 +1,136 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Intel SCIF driver.
+ *
+ */
+#ifndef SCIF_MAP_H
+#define SCIF_MAP_H
+
+#include "../bus/scif_bus.h"
+
+static __always_inline void *
+scif_alloc_coherent(dma_addr_t *dma_handle,
+ struct scif_dev *scifdev, size_t size,
+ gfp_t gfp)
+{
+ void *va;
+
+ if (scifdev_self(scifdev)) {
+ va = kmalloc(size, gfp);
+ if (va)
+ *dma_handle = virt_to_phys(va);
+ } else {
+ va = dma_alloc_coherent(&scifdev->sdev->dev,
+ size, dma_handle, gfp);
+ if (va && scifdev_is_p2p(scifdev))
+ *dma_handle = *dma_handle + scifdev->base_addr;
+ }
+ return va;
+}
+
+static __always_inline void
+scif_free_coherent(void *va, dma_addr_t local,
+ struct scif_dev *scifdev, size_t size)
+{
+ if (scifdev_self(scifdev)) {
+ kfree(va);
+ } else {
+ if (scifdev_is_p2p(scifdev) && local > scifdev->base_addr)
+ local = local - scifdev->base_addr;
+ dma_free_coherent(&scifdev->sdev->dev,
+ size, va, local);
+ }
+}
+
+static __always_inline int
+scif_map_single(dma_addr_t *dma_handle,
+ void *local, struct scif_dev *scifdev, size_t size)
+{
+ int err = 0;
+
+ if (scifdev_self(scifdev)) {
+ *dma_handle = virt_to_phys((local));
+ } else {
+ *dma_handle = dma_map_single(&scifdev->sdev->dev,
+ local, size, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&scifdev->sdev->dev, *dma_handle))
+ err = -ENOMEM;
+ else if (scifdev_is_p2p(scifdev))
+ *dma_handle = *dma_handle + scifdev->base_addr;
+ }
+ if (err)
+ *dma_handle = 0;
+ return err;
+}
+
+static __always_inline void
+scif_unmap_single(dma_addr_t local, struct scif_dev *scifdev,
+ size_t size)
+{
+ if (!scifdev_self(scifdev)) {
+ if (scifdev_is_p2p(scifdev))
+ local = local - scifdev->base_addr;
+ dma_unmap_single(&scifdev->sdev->dev, local,
+ size, DMA_BIDIRECTIONAL);
+ }
+}
+
+static __always_inline void *
+scif_ioremap(dma_addr_t phys, size_t size, struct scif_dev *scifdev)
+{
+ void *out_virt;
+ struct scif_hw_dev *sdev = scifdev->sdev;
+
+ if (scifdev_self(scifdev))
+ out_virt = phys_to_virt(phys);
+ else
+ out_virt = (void __force *)
+ sdev->hw_ops->ioremap(sdev, phys, size);
+ return out_virt;
+}
+
+static __always_inline void
+scif_iounmap(void *virt, size_t len, struct scif_dev *scifdev)
+{
+ if (!scifdev_self(scifdev)) {
+ struct scif_hw_dev *sdev = scifdev->sdev;
+
+ sdev->hw_ops->iounmap(sdev, (void __force __iomem *)virt);
+ }
+}
+
+static __always_inline int
+scif_map_page(dma_addr_t *dma_handle, struct page *page,
+ struct scif_dev *scifdev)
+{
+ int err = 0;
+
+ if (scifdev_self(scifdev)) {
+ *dma_handle = page_to_phys(page);
+ } else {
+ struct scif_hw_dev *sdev = scifdev->sdev;
+ *dma_handle = dma_map_page(&sdev->dev,
+ page, 0x0, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&sdev->dev, *dma_handle))
+ err = -ENOMEM;
+ else if (scifdev_is_p2p(scifdev))
+ *dma_handle = *dma_handle + scifdev->base_addr;
+ }
+ if (err)
+ *dma_handle = 0;
+ return err;
+}
+#endif /* SCIF_MAP_H */