1219820Sjeff/* 2272407Shselasky * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved. 3219820Sjeff * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directory of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff */ 33219820Sjeff 34219820Sjeff#ifndef MLX4_ICM_H 35219820Sjeff#define MLX4_ICM_H 36219820Sjeff 37219820Sjeff#include <linux/list.h> 38219820Sjeff#include <linux/pci.h> 39219820Sjeff#include <linux/mutex.h> 40272407Shselasky#include <linux/scatterlist.h> 41219820Sjeff 42219820Sjeff#define MLX4_ICM_CHUNK_LEN \ 43219820Sjeff ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \ 44219820Sjeff (sizeof (struct scatterlist))) 45219820Sjeff 46219820Sjeffenum { 47219820Sjeff MLX4_ICM_PAGE_SHIFT = 12, 48219820Sjeff MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT, 49219820Sjeff}; 50219820Sjeff 51219820Sjeffstruct mlx4_icm_chunk { 52219820Sjeff struct list_head list; 53219820Sjeff int npages; 54219820Sjeff int nsg; 55219820Sjeff struct scatterlist mem[MLX4_ICM_CHUNK_LEN]; 56219820Sjeff}; 57219820Sjeff 58219820Sjeffstruct mlx4_icm { 59219820Sjeff struct list_head chunk_list; 60219820Sjeff int refcount; 61219820Sjeff}; 62219820Sjeff 63219820Sjeffstruct mlx4_icm_iter { 64219820Sjeff struct mlx4_icm *icm; 65219820Sjeff struct mlx4_icm_chunk *chunk; 66219820Sjeff int page_idx; 67219820Sjeff}; 68219820Sjeff 69219820Sjeffstruct mlx4_dev; 70219820Sjeff 71219820Sjeffstruct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, 72219820Sjeff gfp_t gfp_mask, int coherent); 73219820Sjeffvoid mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); 74219820Sjeff 75255932Salfredint mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); 76255932Salfredvoid mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); 77255932Salfredint mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, 78255932Salfred u32 start, u32 end); 79255932Salfredvoid mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, 80255932Salfred u32 start, u32 end); 81219820Sjeffint mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, 82272407Shselasky u64 virt, int obj_size, u64 nobj, int reserved, 83219820Sjeff int use_lowmem, int use_coherent); 84219820Sjeffvoid mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); 85255932Salfredvoid *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle); 86219820Sjeff 87219820Sjeffstatic inline void mlx4_icm_first(struct mlx4_icm *icm, 88219820Sjeff struct mlx4_icm_iter *iter) 89219820Sjeff{ 90219820Sjeff iter->icm = icm; 91219820Sjeff iter->chunk = list_empty(&icm->chunk_list) ? 92219820Sjeff NULL : list_entry(icm->chunk_list.next, 93219820Sjeff struct mlx4_icm_chunk, list); 94219820Sjeff iter->page_idx = 0; 95219820Sjeff} 96219820Sjeff 97219820Sjeffstatic inline int mlx4_icm_last(struct mlx4_icm_iter *iter) 98219820Sjeff{ 99219820Sjeff return !iter->chunk; 100219820Sjeff} 101219820Sjeff 102219820Sjeffstatic inline void mlx4_icm_next(struct mlx4_icm_iter *iter) 103219820Sjeff{ 104219820Sjeff if (++iter->page_idx >= iter->chunk->nsg) { 105219820Sjeff if (iter->chunk->list.next == &iter->icm->chunk_list) { 106219820Sjeff iter->chunk = NULL; 107219820Sjeff return; 108219820Sjeff } 109219820Sjeff 110219820Sjeff iter->chunk = list_entry(iter->chunk->list.next, 111219820Sjeff struct mlx4_icm_chunk, list); 112219820Sjeff iter->page_idx = 0; 113219820Sjeff } 114219820Sjeff} 115219820Sjeff 116219820Sjeffstatic inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter) 117219820Sjeff{ 118219820Sjeff return sg_dma_address(&iter->chunk->mem[iter->page_idx]); 119219820Sjeff} 120219820Sjeff 121219820Sjeffstatic inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) 122219820Sjeff{ 123219820Sjeff return sg_dma_len(&iter->chunk->mem[iter->page_idx]); 124219820Sjeff} 125219820Sjeff 126272407Shselaskyint mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); 127272407Shselaskyint mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev); 128219820Sjeff 129219820Sjeff#endif /* MLX4_ICM_H */ 130