linux/drivers/staging/rdma/hfi1/dma.c
<<
>>
Prefs
   1/*
   2 *
   3 * This file is provided under a dual BSD/GPLv2 license.  When using or
   4 * redistributing this file, you may do so under either license.
   5 *
   6 * GPL LICENSE SUMMARY
   7 *
   8 * Copyright(c) 2015 Intel Corporation.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of version 2 of the GNU General Public License as
  12 * published by the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful, but
  15 * WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * General Public License for more details.
  18 *
  19 * BSD LICENSE
  20 *
  21 * Copyright(c) 2015 Intel Corporation.
  22 *
  23 * Redistribution and use in source and binary forms, with or without
  24 * modification, are permitted provided that the following conditions
  25 * are met:
  26 *
  27 *  - Redistributions of source code must retain the above copyright
  28 *    notice, this list of conditions and the following disclaimer.
  29 *  - Redistributions in binary form must reproduce the above copyright
  30 *    notice, this list of conditions and the following disclaimer in
  31 *    the documentation and/or other materials provided with the
  32 *    distribution.
  33 *  - Neither the name of Intel Corporation nor the names of its
  34 *    contributors may be used to endorse or promote products derived
  35 *    from this software without specific prior written permission.
  36 *
  37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  40 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  41 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  44 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  45 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  47 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  48 *
  49 */
  50#include <linux/types.h>
  51#include <linux/scatterlist.h>
  52
  53#include "verbs.h"
  54
  55#define BAD_DMA_ADDRESS ((u64) 0)
  56
  57/*
  58 * The following functions implement driver specific replacements
  59 * for the ib_dma_*() functions.
  60 *
  61 * These functions return kernel virtual addresses instead of
  62 * device bus addresses since the driver uses the CPU to copy
  63 * data instead of using hardware DMA.
  64 */
  65
  66static int hfi1_mapping_error(struct ib_device *dev, u64 dma_addr)
  67{
  68        return dma_addr == BAD_DMA_ADDRESS;
  69}
  70
  71static u64 hfi1_dma_map_single(struct ib_device *dev, void *cpu_addr,
  72                               size_t size, enum dma_data_direction direction)
  73{
  74        if (WARN_ON(!valid_dma_direction(direction)))
  75                return BAD_DMA_ADDRESS;
  76
  77        return (u64) cpu_addr;
  78}
  79
  80static void hfi1_dma_unmap_single(struct ib_device *dev, u64 addr, size_t size,
  81                                  enum dma_data_direction direction)
  82{
  83        /* This is a stub, nothing to be done here */
  84}
  85
  86static u64 hfi1_dma_map_page(struct ib_device *dev, struct page *page,
  87                             unsigned long offset, size_t size,
  88                            enum dma_data_direction direction)
  89{
  90        u64 addr;
  91
  92        if (WARN_ON(!valid_dma_direction(direction)))
  93                return BAD_DMA_ADDRESS;
  94
  95        if (offset + size > PAGE_SIZE)
  96                return BAD_DMA_ADDRESS;
  97
  98        addr = (u64) page_address(page);
  99        if (addr)
 100                addr += offset;
 101
 102        return addr;
 103}
 104
 105static void hfi1_dma_unmap_page(struct ib_device *dev, u64 addr, size_t size,
 106                                enum dma_data_direction direction)
 107{
 108        /* This is a stub, nothing to be done here */
 109}
 110
 111static int hfi1_map_sg(struct ib_device *dev, struct scatterlist *sgl,
 112                       int nents, enum dma_data_direction direction)
 113{
 114        struct scatterlist *sg;
 115        u64 addr;
 116        int i;
 117        int ret = nents;
 118
 119        if (WARN_ON(!valid_dma_direction(direction)))
 120                return BAD_DMA_ADDRESS;
 121
 122        for_each_sg(sgl, sg, nents, i) {
 123                addr = (u64) page_address(sg_page(sg));
 124                if (!addr) {
 125                        ret = 0;
 126                        break;
 127                }
 128                sg->dma_address = addr + sg->offset;
 129#ifdef CONFIG_NEED_SG_DMA_LENGTH
 130                sg->dma_length = sg->length;
 131#endif
 132        }
 133        return ret;
 134}
 135
 136static void hfi1_unmap_sg(struct ib_device *dev,
 137                          struct scatterlist *sg, int nents,
 138                         enum dma_data_direction direction)
 139{
 140        /* This is a stub, nothing to be done here */
 141}
 142
 143static void hfi1_sync_single_for_cpu(struct ib_device *dev, u64 addr,
 144                                     size_t size, enum dma_data_direction dir)
 145{
 146}
 147
 148static void hfi1_sync_single_for_device(struct ib_device *dev, u64 addr,
 149                                        size_t size,
 150                                        enum dma_data_direction dir)
 151{
 152}
 153
 154static void *hfi1_dma_alloc_coherent(struct ib_device *dev, size_t size,
 155                                     u64 *dma_handle, gfp_t flag)
 156{
 157        struct page *p;
 158        void *addr = NULL;
 159
 160        p = alloc_pages(flag, get_order(size));
 161        if (p)
 162                addr = page_address(p);
 163        if (dma_handle)
 164                *dma_handle = (u64) addr;
 165        return addr;
 166}
 167
 168static void hfi1_dma_free_coherent(struct ib_device *dev, size_t size,
 169                                   void *cpu_addr, u64 dma_handle)
 170{
 171        free_pages((unsigned long) cpu_addr, get_order(size));
 172}
 173
 174struct ib_dma_mapping_ops hfi1_dma_mapping_ops = {
 175        .mapping_error = hfi1_mapping_error,
 176        .map_single = hfi1_dma_map_single,
 177        .unmap_single = hfi1_dma_unmap_single,
 178        .map_page = hfi1_dma_map_page,
 179        .unmap_page = hfi1_dma_unmap_page,
 180        .map_sg = hfi1_map_sg,
 181        .unmap_sg = hfi1_unmap_sg,
 182        .sync_single_for_cpu = hfi1_sync_single_for_cpu,
 183        .sync_single_for_device = hfi1_sync_single_for_device,
 184        .alloc_coherent = hfi1_dma_alloc_coherent,
 185        .free_coherent = hfi1_dma_free_coherent
 186};
 187