18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 68c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 98c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 128c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 138c2ecf20Sopenharmony_ci * conditions are met: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 168c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 178c2ecf20Sopenharmony_ci * disclaimer. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 208c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 218c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 228c2ecf20Sopenharmony_ci * provided with the distribution. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 258c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 268c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 278c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 288c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 298c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 308c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 318c2ecf20Sopenharmony_ci * SOFTWARE. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#ifndef MLX4_ICM_H 358c2ecf20Sopenharmony_ci#define MLX4_ICM_H 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <linux/list.h> 388c2ecf20Sopenharmony_ci#include <linux/pci.h> 398c2ecf20Sopenharmony_ci#include <linux/mutex.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define MLX4_ICM_CHUNK_LEN \ 428c2ecf20Sopenharmony_ci ((256 - sizeof(struct list_head) - 2 * sizeof(int)) / \ 438c2ecf20Sopenharmony_ci (sizeof(struct scatterlist))) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cienum { 468c2ecf20Sopenharmony_ci MLX4_ICM_PAGE_SHIFT = 12, 478c2ecf20Sopenharmony_ci MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT, 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistruct mlx4_icm_buf { 518c2ecf20Sopenharmony_ci void *addr; 528c2ecf20Sopenharmony_ci size_t size; 538c2ecf20Sopenharmony_ci dma_addr_t dma_addr; 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistruct mlx4_icm_chunk { 578c2ecf20Sopenharmony_ci struct list_head list; 588c2ecf20Sopenharmony_ci int npages; 598c2ecf20Sopenharmony_ci int nsg; 608c2ecf20Sopenharmony_ci bool coherent; 618c2ecf20Sopenharmony_ci union { 628c2ecf20Sopenharmony_ci struct scatterlist sg[MLX4_ICM_CHUNK_LEN]; 638c2ecf20Sopenharmony_ci struct mlx4_icm_buf buf[MLX4_ICM_CHUNK_LEN]; 648c2ecf20Sopenharmony_ci }; 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct mlx4_icm { 688c2ecf20Sopenharmony_ci struct list_head chunk_list; 698c2ecf20Sopenharmony_ci int refcount; 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistruct mlx4_icm_iter { 738c2ecf20Sopenharmony_ci struct mlx4_icm *icm; 748c2ecf20Sopenharmony_ci struct mlx4_icm_chunk *chunk; 758c2ecf20Sopenharmony_ci int page_idx; 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistruct mlx4_dev; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, 818c2ecf20Sopenharmony_ci gfp_t gfp_mask, int coherent); 828c2ecf20Sopenharmony_civoid mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ciint mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); 858c2ecf20Sopenharmony_civoid mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); 868c2ecf20Sopenharmony_ciint mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, 878c2ecf20Sopenharmony_ci u32 start, u32 end); 888c2ecf20Sopenharmony_civoid mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, 898c2ecf20Sopenharmony_ci u32 start, u32 end); 908c2ecf20Sopenharmony_ciint mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, 918c2ecf20Sopenharmony_ci u64 virt, int obj_size, u32 nobj, int reserved, 928c2ecf20Sopenharmony_ci int use_lowmem, int use_coherent); 938c2ecf20Sopenharmony_civoid mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); 948c2ecf20Sopenharmony_civoid *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline void mlx4_icm_first(struct mlx4_icm *icm, 978c2ecf20Sopenharmony_ci struct mlx4_icm_iter *iter) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci iter->icm = icm; 1008c2ecf20Sopenharmony_ci iter->chunk = list_empty(&icm->chunk_list) ? 1018c2ecf20Sopenharmony_ci NULL : list_entry(icm->chunk_list.next, 1028c2ecf20Sopenharmony_ci struct mlx4_icm_chunk, list); 1038c2ecf20Sopenharmony_ci iter->page_idx = 0; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic inline int mlx4_icm_last(struct mlx4_icm_iter *iter) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci return !iter->chunk; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic inline void mlx4_icm_next(struct mlx4_icm_iter *iter) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci if (++iter->page_idx >= iter->chunk->nsg) { 1148c2ecf20Sopenharmony_ci if (iter->chunk->list.next == &iter->icm->chunk_list) { 1158c2ecf20Sopenharmony_ci iter->chunk = NULL; 1168c2ecf20Sopenharmony_ci return; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci iter->chunk = list_entry(iter->chunk->list.next, 1208c2ecf20Sopenharmony_ci struct mlx4_icm_chunk, list); 1218c2ecf20Sopenharmony_ci iter->page_idx = 0; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci if (iter->chunk->coherent) 1288c2ecf20Sopenharmony_ci return iter->chunk->buf[iter->page_idx].dma_addr; 1298c2ecf20Sopenharmony_ci else 1308c2ecf20Sopenharmony_ci return sg_dma_address(&iter->chunk->sg[iter->page_idx]); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci if (iter->chunk->coherent) 1368c2ecf20Sopenharmony_ci return iter->chunk->buf[iter->page_idx].size; 1378c2ecf20Sopenharmony_ci else 1388c2ecf20Sopenharmony_ci return sg_dma_len(&iter->chunk->sg[iter->page_idx]); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ciint mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); 1428c2ecf20Sopenharmony_ciint mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#endif /* MLX4_ICM_H */ 145