1219820Sjeff/* 2219820Sjeff * Copyright (c) 2005, 2006, 2007, 2008 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> 40219820Sjeff 41219820Sjeff#define MLX4_ICM_CHUNK_LEN \ 42219820Sjeff ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \ 43219820Sjeff (sizeof (struct scatterlist))) 44219820Sjeff 45219820Sjeffenum { 46219820Sjeff MLX4_ICM_PAGE_SHIFT = 12, 47219820Sjeff MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT, 48219820Sjeff}; 49219820Sjeff 50219820Sjeffstruct mlx4_icm_chunk { 51219820Sjeff struct list_head list; 52219820Sjeff int npages; 53219820Sjeff int nsg; 54219820Sjeff struct scatterlist mem[MLX4_ICM_CHUNK_LEN]; 55219820Sjeff}; 56219820Sjeff 57219820Sjeffstruct mlx4_icm { 58219820Sjeff struct list_head chunk_list; 59219820Sjeff int refcount; 60219820Sjeff}; 61219820Sjeff 62219820Sjeffstruct mlx4_icm_iter { 63219820Sjeff struct mlx4_icm *icm; 64219820Sjeff struct mlx4_icm_chunk *chunk; 65219820Sjeff int page_idx; 66219820Sjeff}; 67219820Sjeff 68219820Sjeffstruct mlx4_dev; 69219820Sjeff 70219820Sjeffstruct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, 71219820Sjeff gfp_t gfp_mask, int coherent); 72219820Sjeffvoid mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); 73219820Sjeff 74255932Salfredint mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); 75255932Salfredvoid mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); 76255932Salfredint mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, 77255932Salfred u32 start, u32 end); 78255932Salfredvoid mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, 79255932Salfred u32 start, u32 end); 80219820Sjeffint mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, 81255932Salfred u64 virt, int obj_size, u32 nobj, int reserved, 82219820Sjeff int use_lowmem, int use_coherent); 83219820Sjeffvoid mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); 84255932Salfredvoid *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle); 85219820Sjeff 86219820Sjeffstatic inline void mlx4_icm_first(struct mlx4_icm *icm, 87219820Sjeff struct mlx4_icm_iter *iter) 88219820Sjeff{ 89219820Sjeff iter->icm = icm; 90219820Sjeff iter->chunk = list_empty(&icm->chunk_list) ? 91219820Sjeff NULL : list_entry(icm->chunk_list.next, 92219820Sjeff struct mlx4_icm_chunk, list); 93219820Sjeff iter->page_idx = 0; 94219820Sjeff} 95219820Sjeff 96219820Sjeffstatic inline int mlx4_icm_last(struct mlx4_icm_iter *iter) 97219820Sjeff{ 98219820Sjeff return !iter->chunk; 99219820Sjeff} 100219820Sjeff 101219820Sjeffstatic inline void mlx4_icm_next(struct mlx4_icm_iter *iter) 102219820Sjeff{ 103219820Sjeff if (++iter->page_idx >= iter->chunk->nsg) { 104219820Sjeff if (iter->chunk->list.next == &iter->icm->chunk_list) { 105219820Sjeff iter->chunk = NULL; 106219820Sjeff return; 107219820Sjeff } 108219820Sjeff 109219820Sjeff iter->chunk = list_entry(iter->chunk->list.next, 110219820Sjeff struct mlx4_icm_chunk, list); 111219820Sjeff iter->page_idx = 0; 112219820Sjeff } 113219820Sjeff} 114219820Sjeff 115219820Sjeffstatic inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter) 116219820Sjeff{ 117219820Sjeff return sg_dma_address(&iter->chunk->mem[iter->page_idx]); 118219820Sjeff} 119219820Sjeff 120219820Sjeffstatic inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) 121219820Sjeff{ 122219820Sjeff return sg_dma_len(&iter->chunk->mem[iter->page_idx]); 123219820Sjeff} 124219820Sjeff 125219820Sjeff 126219820Sjeff#endif /* MLX4_ICM_H */ 127