1/* 2 * Intel MIC Platform Software Stack (MPSS) 3 * 4 * Copyright(c) 2014 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License, version 2, as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * Intel SCIF driver. 16 * 17 */ 18#ifndef SCIF_MAP_H 19#define SCIF_MAP_H 20 21#include "../bus/scif_bus.h" 22 23static __always_inline void * 24scif_alloc_coherent(dma_addr_t *dma_handle, 25 struct scif_dev *scifdev, size_t size, 26 gfp_t gfp) 27{ 28 void *va; 29 30 if (scifdev_self(scifdev)) { 31 va = kmalloc(size, gfp); 32 if (va) 33 *dma_handle = virt_to_phys(va); 34 } else { 35 va = dma_alloc_coherent(&scifdev->sdev->dev, 36 size, dma_handle, gfp); 37 if (va && scifdev_is_p2p(scifdev)) 38 *dma_handle = *dma_handle + scifdev->base_addr; 39 } 40 return va; 41} 42 43static __always_inline void 44scif_free_coherent(void *va, dma_addr_t local, 45 struct scif_dev *scifdev, size_t size) 46{ 47 if (scifdev_self(scifdev)) { 48 kfree(va); 49 } else { 50 if (scifdev_is_p2p(scifdev) && local > scifdev->base_addr) 51 local = local - scifdev->base_addr; 52 dma_free_coherent(&scifdev->sdev->dev, 53 size, va, local); 54 } 55} 56 57static __always_inline int 58scif_map_single(dma_addr_t *dma_handle, 59 void *local, struct scif_dev *scifdev, size_t size) 60{ 61 int err = 0; 62 63 if (scifdev_self(scifdev)) { 64 *dma_handle = virt_to_phys((local)); 65 } else { 66 *dma_handle = dma_map_single(&scifdev->sdev->dev, 67 local, size, DMA_BIDIRECTIONAL); 68 if (dma_mapping_error(&scifdev->sdev->dev, *dma_handle)) 69 err = -ENOMEM; 70 else if (scifdev_is_p2p(scifdev)) 71 *dma_handle = *dma_handle + scifdev->base_addr; 72 } 73 if (err) 74 *dma_handle = 0; 75 return err; 76} 77 78static __always_inline void 79scif_unmap_single(dma_addr_t local, struct scif_dev *scifdev, 80 size_t size) 81{ 82 if (!scifdev_self(scifdev)) { 83 if (scifdev_is_p2p(scifdev)) 84 local = local - scifdev->base_addr; 85 dma_unmap_single(&scifdev->sdev->dev, local, 86 size, DMA_BIDIRECTIONAL); 87 } 88} 89 90static __always_inline void * 91scif_ioremap(dma_addr_t phys, size_t size, struct scif_dev *scifdev) 92{ 93 void *out_virt; 94 struct scif_hw_dev *sdev = scifdev->sdev; 95 96 if (scifdev_self(scifdev)) 97 out_virt = phys_to_virt(phys); 98 else 99 out_virt = (void __force *) 100 sdev->hw_ops->ioremap(sdev, phys, size); 101 return out_virt; 102} 103 104static __always_inline void 105scif_iounmap(void *virt, size_t len, struct scif_dev *scifdev) 106{ 107 if (!scifdev_self(scifdev)) { 108 struct scif_hw_dev *sdev = scifdev->sdev; 109 110 sdev->hw_ops->iounmap(sdev, (void __force __iomem *)virt); 111 } 112} 113 114static __always_inline int 115scif_map_page(dma_addr_t *dma_handle, struct page *page, 116 struct scif_dev *scifdev) 117{ 118 int err = 0; 119 120 if (scifdev_self(scifdev)) { 121 *dma_handle = page_to_phys(page); 122 } else { 123 struct scif_hw_dev *sdev = scifdev->sdev; 124 *dma_handle = dma_map_page(&sdev->dev, 125 page, 0x0, PAGE_SIZE, 126 DMA_BIDIRECTIONAL); 127 if (dma_mapping_error(&sdev->dev, *dma_handle)) 128 err = -ENOMEM; 129 else if (scifdev_is_p2p(scifdev)) 130 *dma_handle = *dma_handle + scifdev->base_addr; 131 } 132 if (err) 133 *dma_handle = 0; 134 return err; 135} 136#endif /* SCIF_MAP_H */ 137