linux/drivers/misc/mic/scif/scif_map.h
<<
>>
Prefs
   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