18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2005 Cisco Systems. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2005 Mellanox Technologies. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 78c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 138c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 178c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 188c2ecf20Sopenharmony_ci * disclaimer. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 218c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 228c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 238c2ecf20Sopenharmony_ci * provided with the distribution. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 328c2ecf20Sopenharmony_ci * SOFTWARE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#ifndef MTHCA_MEMFREE_H 368c2ecf20Sopenharmony_ci#define MTHCA_MEMFREE_H 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include <linux/list.h> 398c2ecf20Sopenharmony_ci#include <linux/mutex.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define MTHCA_ICM_CHUNK_LEN \ 428c2ecf20Sopenharmony_ci ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \ 438c2ecf20Sopenharmony_ci (sizeof (struct scatterlist))) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cienum { 468c2ecf20Sopenharmony_ci MTHCA_ICM_PAGE_SHIFT = 12, 478c2ecf20Sopenharmony_ci MTHCA_ICM_PAGE_SIZE = 1 << MTHCA_ICM_PAGE_SHIFT, 488c2ecf20Sopenharmony_ci MTHCA_DB_REC_PER_PAGE = MTHCA_ICM_PAGE_SIZE / 8 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistruct mthca_icm_chunk { 528c2ecf20Sopenharmony_ci struct list_head list; 538c2ecf20Sopenharmony_ci int npages; 548c2ecf20Sopenharmony_ci int nsg; 558c2ecf20Sopenharmony_ci struct scatterlist mem[MTHCA_ICM_CHUNK_LEN]; 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct mthca_icm { 598c2ecf20Sopenharmony_ci struct list_head chunk_list; 608c2ecf20Sopenharmony_ci int refcount; 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistruct mthca_icm_table { 648c2ecf20Sopenharmony_ci u64 virt; 658c2ecf20Sopenharmony_ci int num_icm; 668c2ecf20Sopenharmony_ci int num_obj; 678c2ecf20Sopenharmony_ci int obj_size; 688c2ecf20Sopenharmony_ci int lowmem; 698c2ecf20Sopenharmony_ci int coherent; 708c2ecf20Sopenharmony_ci struct mutex mutex; 718c2ecf20Sopenharmony_ci struct mthca_icm *icm[]; 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistruct mthca_icm_iter { 758c2ecf20Sopenharmony_ci struct mthca_icm *icm; 768c2ecf20Sopenharmony_ci struct mthca_icm_chunk *chunk; 778c2ecf20Sopenharmony_ci int page_idx; 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct mthca_dev; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistruct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages, 838c2ecf20Sopenharmony_ci gfp_t gfp_mask, int coherent); 848c2ecf20Sopenharmony_civoid mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm, int coherent); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistruct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, 878c2ecf20Sopenharmony_ci u64 virt, int obj_size, 888c2ecf20Sopenharmony_ci int nobj, int reserved, 898c2ecf20Sopenharmony_ci int use_lowmem, int use_coherent); 908c2ecf20Sopenharmony_civoid mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table); 918c2ecf20Sopenharmony_ciint mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj); 928c2ecf20Sopenharmony_civoid mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj); 938c2ecf20Sopenharmony_civoid *mthca_table_find(struct mthca_icm_table *table, int obj, dma_addr_t *dma_handle); 948c2ecf20Sopenharmony_ciint mthca_table_get_range(struct mthca_dev *dev, struct mthca_icm_table *table, 958c2ecf20Sopenharmony_ci int start, int end); 968c2ecf20Sopenharmony_civoid mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table, 978c2ecf20Sopenharmony_ci int start, int end); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic inline void mthca_icm_first(struct mthca_icm *icm, 1008c2ecf20Sopenharmony_ci struct mthca_icm_iter *iter) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci iter->icm = icm; 1038c2ecf20Sopenharmony_ci iter->chunk = list_empty(&icm->chunk_list) ? 1048c2ecf20Sopenharmony_ci NULL : list_entry(icm->chunk_list.next, 1058c2ecf20Sopenharmony_ci struct mthca_icm_chunk, list); 1068c2ecf20Sopenharmony_ci iter->page_idx = 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic inline int mthca_icm_last(struct mthca_icm_iter *iter) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci return !iter->chunk; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic inline void mthca_icm_next(struct mthca_icm_iter *iter) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci if (++iter->page_idx >= iter->chunk->nsg) { 1178c2ecf20Sopenharmony_ci if (iter->chunk->list.next == &iter->icm->chunk_list) { 1188c2ecf20Sopenharmony_ci iter->chunk = NULL; 1198c2ecf20Sopenharmony_ci return; 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci iter->chunk = list_entry(iter->chunk->list.next, 1238c2ecf20Sopenharmony_ci struct mthca_icm_chunk, list); 1248c2ecf20Sopenharmony_ci iter->page_idx = 0; 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic inline dma_addr_t mthca_icm_addr(struct mthca_icm_iter *iter) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci return sg_dma_address(&iter->chunk->mem[iter->page_idx]); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic inline unsigned long mthca_icm_size(struct mthca_icm_iter *iter) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci return sg_dma_len(&iter->chunk->mem[iter->page_idx]); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistruct mthca_db_page { 1398c2ecf20Sopenharmony_ci DECLARE_BITMAP(used, MTHCA_DB_REC_PER_PAGE); 1408c2ecf20Sopenharmony_ci __be64 *db_rec; 1418c2ecf20Sopenharmony_ci dma_addr_t mapping; 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistruct mthca_db_table { 1458c2ecf20Sopenharmony_ci int npages; 1468c2ecf20Sopenharmony_ci int max_group1; 1478c2ecf20Sopenharmony_ci int min_group2; 1488c2ecf20Sopenharmony_ci struct mthca_db_page *page; 1498c2ecf20Sopenharmony_ci struct mutex mutex; 1508c2ecf20Sopenharmony_ci}; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cienum mthca_db_type { 1538c2ecf20Sopenharmony_ci MTHCA_DB_TYPE_INVALID = 0x0, 1548c2ecf20Sopenharmony_ci MTHCA_DB_TYPE_CQ_SET_CI = 0x1, 1558c2ecf20Sopenharmony_ci MTHCA_DB_TYPE_CQ_ARM = 0x2, 1568c2ecf20Sopenharmony_ci MTHCA_DB_TYPE_SQ = 0x3, 1578c2ecf20Sopenharmony_ci MTHCA_DB_TYPE_RQ = 0x4, 1588c2ecf20Sopenharmony_ci MTHCA_DB_TYPE_SRQ = 0x5, 1598c2ecf20Sopenharmony_ci MTHCA_DB_TYPE_GROUP_SEP = 0x7 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistruct mthca_user_db_table; 1638c2ecf20Sopenharmony_cistruct mthca_uar; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciint mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, 1668c2ecf20Sopenharmony_ci struct mthca_user_db_table *db_tab, int index, u64 uaddr); 1678c2ecf20Sopenharmony_civoid mthca_unmap_user_db(struct mthca_dev *dev, struct mthca_uar *uar, 1688c2ecf20Sopenharmony_ci struct mthca_user_db_table *db_tab, int index); 1698c2ecf20Sopenharmony_cistruct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev); 1708c2ecf20Sopenharmony_civoid mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar, 1718c2ecf20Sopenharmony_ci struct mthca_user_db_table *db_tab); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ciint mthca_init_db_tab(struct mthca_dev *dev); 1748c2ecf20Sopenharmony_civoid mthca_cleanup_db_tab(struct mthca_dev *dev); 1758c2ecf20Sopenharmony_ciint mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type, 1768c2ecf20Sopenharmony_ci u32 qn, __be32 **db); 1778c2ecf20Sopenharmony_civoid mthca_free_db(struct mthca_dev *dev, int type, int db_index); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci#endif /* MTHCA_MEMFREE_H */ 180