Path: blob/master/drivers/infiniband/hw/ipath/ipath_dma.c
15112 views
/*1* Copyright (c) 2006 QLogic, Corporation. All rights reserved.2*3* This software is available to you under a choice of one of two4* licenses. You may choose to be licensed under the terms of the GNU5* General Public License (GPL) Version 2, available from the file6* COPYING in the main directory of this source tree, or the7* OpenIB.org BSD license below:8*9* Redistribution and use in source and binary forms, with or10* without modification, are permitted provided that the following11* conditions are met:12*13* - Redistributions of source code must retain the above14* copyright notice, this list of conditions and the following15* disclaimer.16*17* - Redistributions in binary form must reproduce the above18* copyright notice, this list of conditions and the following19* disclaimer in the documentation and/or other materials20* provided with the distribution.21*22* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,23* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF24* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND25* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS26* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN27* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN28* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE29* SOFTWARE.30*/3132#include <linux/scatterlist.h>33#include <linux/gfp.h>34#include <rdma/ib_verbs.h>3536#include "ipath_verbs.h"3738#define BAD_DMA_ADDRESS ((u64) 0)3940/*41* The following functions implement driver specific replacements42* for the ib_dma_*() functions.43*44* These functions return kernel virtual addresses instead of45* device bus addresses since the driver uses the CPU to copy46* data instead of using hardware DMA.47*/4849static int ipath_mapping_error(struct ib_device *dev, u64 dma_addr)50{51return dma_addr == BAD_DMA_ADDRESS;52}5354static u64 ipath_dma_map_single(struct ib_device *dev,55void *cpu_addr, size_t size,56enum dma_data_direction direction)57{58BUG_ON(!valid_dma_direction(direction));59return (u64) cpu_addr;60}6162static void ipath_dma_unmap_single(struct ib_device *dev,63u64 addr, size_t size,64enum dma_data_direction direction)65{66BUG_ON(!valid_dma_direction(direction));67}6869static u64 ipath_dma_map_page(struct ib_device *dev,70struct page *page,71unsigned long offset,72size_t size,73enum dma_data_direction direction)74{75u64 addr;7677BUG_ON(!valid_dma_direction(direction));7879if (offset + size > PAGE_SIZE) {80addr = BAD_DMA_ADDRESS;81goto done;82}8384addr = (u64) page_address(page);85if (addr)86addr += offset;87/* TODO: handle highmem pages */8889done:90return addr;91}9293static void ipath_dma_unmap_page(struct ib_device *dev,94u64 addr, size_t size,95enum dma_data_direction direction)96{97BUG_ON(!valid_dma_direction(direction));98}99100static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sgl,101int nents, enum dma_data_direction direction)102{103struct scatterlist *sg;104u64 addr;105int i;106int ret = nents;107108BUG_ON(!valid_dma_direction(direction));109110for_each_sg(sgl, sg, nents, i) {111addr = (u64) page_address(sg_page(sg));112/* TODO: handle highmem pages */113if (!addr) {114ret = 0;115break;116}117}118return ret;119}120121static void ipath_unmap_sg(struct ib_device *dev,122struct scatterlist *sg, int nents,123enum dma_data_direction direction)124{125BUG_ON(!valid_dma_direction(direction));126}127128static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg)129{130u64 addr = (u64) page_address(sg_page(sg));131132if (addr)133addr += sg->offset;134return addr;135}136137static unsigned int ipath_sg_dma_len(struct ib_device *dev,138struct scatterlist *sg)139{140return sg->length;141}142143static void ipath_sync_single_for_cpu(struct ib_device *dev,144u64 addr,145size_t size,146enum dma_data_direction dir)147{148}149150static void ipath_sync_single_for_device(struct ib_device *dev,151u64 addr,152size_t size,153enum dma_data_direction dir)154{155}156157static void *ipath_dma_alloc_coherent(struct ib_device *dev, size_t size,158u64 *dma_handle, gfp_t flag)159{160struct page *p;161void *addr = NULL;162163p = alloc_pages(flag, get_order(size));164if (p)165addr = page_address(p);166if (dma_handle)167*dma_handle = (u64) addr;168return addr;169}170171static void ipath_dma_free_coherent(struct ib_device *dev, size_t size,172void *cpu_addr, u64 dma_handle)173{174free_pages((unsigned long) cpu_addr, get_order(size));175}176177struct ib_dma_mapping_ops ipath_dma_mapping_ops = {178ipath_mapping_error,179ipath_dma_map_single,180ipath_dma_unmap_single,181ipath_dma_map_page,182ipath_dma_unmap_page,183ipath_map_sg,184ipath_unmap_sg,185ipath_sg_dma_address,186ipath_sg_dma_len,187ipath_sync_single_for_cpu,188ipath_sync_single_for_device,189ipath_dma_alloc_coherent,190ipath_dma_free_coherent191};192193194